//TestPostApplyDeploymentJobs test job Task
//TODO: This test requires a server profile to have been created
func TestPostApplyDeploymentJobs(t *testing.T) {
	var (
		d *ICSPTest
		c *icsp.ICSPClient
	)
	if os.Getenv("ICSP_TEST_ACCEPTANCE") == "true" {
		d, c = getTestDriverA()
		if c == nil {
			t.Fatalf("Failed to execute getTestDriver() ")
		}

		serialNumber := d.Tc.GetTestData(d.Env, "FreeICSPSerialNumber").(string)
		s, err := c.GetServerBySerialNumber(serialNumber) // fake serial number

		// (c *ICSPClient) GetJob(u ODSUri) (Job, error) {
		// create a jt *JobTask object
		// JobURI
		var jt *icsp.JobTask
		var testURL utils.Nstring
		testURL = "/rest/os-deployment-jobs/5350001"
		jt = &icsp.JobTask{
			JobURI: icsp.ODSUri{URI: testURL},
			Client: c,
		}
		var findprops []string
		findprops = append(findprops, "public_ip")
		err = c.PostApplyDeploymentJobs(jt, s, findprops)
		assert.NoError(t, err, "PostApplyDeploymentJobs threw error -> %s, %+v\n", err, jt)
	}
}
// TODO TestSetStaticInterface - verify we can set one of the servers interface to static
// TesttoJSON - verify we can return a json string of the NetConfig object
func TestToJSON(t *testing.T) {
	var (
		d *ICSPTest
		c *icsp.ICSPClient
	)
	if os.Getenv("ICSP_TEST_ACCEPTANCE") == "true" {
		d, c = getTestDriverA()
		if c == nil {
			t.Fatalf("Failed to execute getTestDriver() ")
		}

		serialNumber := d.Tc.GetTestData(d.Env, "FreeICSPSerialNumber").(string)
		s, err := c.GetServerBySerialNumber(serialNumber) // fake serial number
		assert.NoError(t, err, "should GetServerBySerialNumber -> %s, %+v", err, s)

		err = GetNetConfigTestData()
		assert.NoError(t, err, "should GetNetConfigTestData -> %s", err)

		var emptyconfig utils.Nstring
		emptyconfig.Nil()
		n.AddAllDHCP(s.Interfaces, false, emptyconfig)
		data, err := n.ToJSON()
		assert.NoError(t, err, "Should convert object to json, %s", err)
		log.Infof("n JSON -> %s", data)
		assert.True(t, len(data) > 0, "Should have some data")
	}
}
// Test for expired key and see if RefreshLogin can restore the key if we have a bad key
func TestSessionExpiredKey(t *testing.T) {
	var (
		c *icsp.ICSPClient
		d *ICSPTest
	)
	if os.Getenv("ONEVIEW_TEST_ACCEPTANCE") == "true" {
		d, c = getTestDriverA()
		if c == nil {
			t.Fatalf("Failed to execute getTestDriver() ")
		}
		err := c.RefreshLogin()
		log.Debugf(" login key -> %s", c.APIKey)
		assert.NoError(t, err, "RefreshLogin threw error -> %s", err)
		// force key to timeout
		err = c.SetIdleTimeout(800)
		assert.NoError(t, err, "SetIdleTimeout threw error -> %s", err)

		// 1 millisecond and we should be timeout with the current key
		time.Sleep(1 * time.Millisecond)

		// verify we are timed out
		_, err = c.GetIdleTimeout()
		assert.Error(t, err, "should be 404 not found -> %s ", err)

		// verify that we can access something from icps with this client
		// This should not fail because it uses RefreshLogin to get a new login session and avoid timeout
		serialNumber := d.Tc.GetTestData(d.Env, "SerialNumber").(string)
		s, err := c.GetServerBySerialNumber(serialNumber)
		assert.NoError(t, err, "GetServerBySerialNumber threw error -> %s, server -> %+v", err, s)
	}

}
// TestNetConfigSave - save netconfig to hpsa_netconfig
func TestNetConfigSave(t *testing.T) {
	var (
		d *ICSPTest
		c *icsp.ICSPClient
	)
	if os.Getenv("ICSP_TEST_ACCEPTANCE") == "true" {
		d, c = getTestDriverA()
		if c == nil {
			t.Fatalf("Failed to execute getTestDriver() ")
		}

		serialNumber := d.Tc.GetTestData(d.Env, "FreeICSPSerialNumber").(string)
		s, err := c.GetServerBySerialNumber(serialNumber) // fake serial number
		assert.NoError(t, err, "should GetServerBySerialNumber -> %s, %+v", err, s)

		err = GetNetConfigTestData()
		assert.NoError(t, err, "should GetNetConfigTestData -> %s", err)

		var emptyconfig utils.Nstring
		emptyconfig.Nil()
		n.AddAllDHCP(s.Interfaces, false, emptyconfig)
		s, err = n.Save(s)
		assert.NoError(t, err, "should Save -> %s, %+v", err, s)
		// place those strings into custom attributes
		_, err = c.SaveServer(s)
		assert.NoError(t, err, "should SaveServer -> %s, %+v", err, s)
	}
}
//TestNetConfigAddAllDHCP - verify we can convert a servers interfaces to dhcp
func TestNetConfigAddAllDHCP(t *testing.T) {
	var (
		d *ICSPTest
		c *icsp.ICSPClient
	)
	if os.Getenv("ICSP_TEST_ACCEPTANCE") == "true" {
		d, c = getTestDriverA()
		if c == nil {
			t.Fatalf("Failed to execute getTestDriver() ")
		}

		serialNumber := d.Tc.GetTestData(d.Env, "FreeICSPSerialNumber").(string)
		s, err := c.GetServerBySerialNumber(serialNumber) // fake serial number
		assert.NoError(t, err, "should GetServerBySerialNumber -> %s, %+v", err, s)

		err = GetNetConfigTestData()
		assert.NoError(t, err, "should GetNetConfigTestData -> %s", err)

		var emptyconfig utils.Nstring
		emptyconfig.Nil()
		n.AddAllDHCP(s.Interfaces, false, emptyconfig)
		for _, neti := range n.Interfaces {
			assert.True(t, neti.DHCPv4, fmt.Sprintf("Should have interface, %s, dhcpv4 enabled", neti.MACAddr))
			assert.False(t, neti.IPv6Autoconfig, "Should have ipv6 auto config as false")
		}
	}
}
// TestSaveServer implement save server
func TestSaveServer(t *testing.T) {
	var (
		d *ICSPTest
		c *icsp.ICSPClient
	)
	if os.Getenv("ICSP_TEST_ACCEPTANCE") == "true" {
		log.Debug("implements acceptance test for TestCreateServer")
		d, c = getTestDriverA()
		if c == nil {
			t.Fatalf("Failed to execute getTestDriver() ")
		}
		// get a Server
		serialNumber := d.Tc.GetTestData(d.Env, "FreeBladeSerialNumber").(string)
		s, err := c.GetServerBySerialNumber(serialNumber)
		assert.NoError(t, err, "GetServerBySerialNumber threw error -> %s, %+v\n", err, s)
		// set a custom attribute
		s.SetCustomAttribute("docker_user", "server", "docker")
		// use test keys like from https://github.com/mitchellh/vagrant/tree/master/keys
		// private key from https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant
		s.SetCustomAttribute("public_key", "server", "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ==")
		// save a server
		news, err := c.SaveServer(s)
		assert.NoError(t, err, "SaveServer threw error -> %s, %+v\n", err, news)
		assert.Equal(t, s.UUID, news.UUID, "Should return a server with the same UUID")
		// verify that the server attribute was saved by getting the server again and checking the value
		_, testValue2 := s.GetValueItem("docker_user", "server")
		assert.Equal(t, "docker", testValue2.Value, "Should return the saved custom attribute")
	} else {
		log.Debug("implements unit test for TestCreateServer")
		var s icsp.Server
		_, c = getTestDriverU()
		s, err := c.SaveServer(s)
		assert.Error(t, err, "SaveServer threw error -> %s, %+v\n", err, s)
	}
}
// func (s Server) GetPublicIPV4() (string, error) {
// TestGetPublicIPV4 try to test for getting interface from custom attribute
func TestGetPublicIPV4(t *testing.T) {
	var (
		d            *ICSPTest
		c            *icsp.ICSPClient
		serialNumber string
	)
	if os.Getenv("ICSP_TEST_ACCEPTANCE") == "true" {
		log.Debug("implements acceptance test for TestGetPublicIPV4")
		d, c = getTestDriverA()
		if c == nil {
			t.Fatalf("Failed to execute getTestDriver() ")
		}
		if os.Getenv("ONEVIEW_TEST_PROVISION") == "true" {
			serialNumber = d.Tc.GetTestData(d.Env, "FreeICSPSerialNumber").(string)
		} else {
			serialNumber = d.Tc.GetTestData(d.Env, "SerialNumber").(string)
		}
		s, err := c.GetServerBySerialNumber(serialNumber)
		testIP, err := s.GetPublicIPV4()
		assert.NoError(t, err, "Should GetPublicIPV4 without error -> %s, %+v\n", err, s)
		log.Debugf(" testIP -> %s", testIP)
		assert.True(t, (len(testIP) > 0), "Should return an ip address string")
	} else {
		// TODO: implement a test
		// need to simplate createing public_interface custom attribute object
		// need to read custom attribute object, see server_customattribute_test.go
		log.Debug("implements unit test for TestGetPublicIPV4")
	}
}
// TestPreApplyDeploymentJobs - setup some information from icsp
//TODO: This test requires a server profile to have been created
func TestPreApplyDeploymentJobs(t *testing.T) {
	var (
		d                     *ICSPTest
		c                     *icsp.ICSPClient
		serialNumber, macAddr string
	)
	if os.Getenv("ICSP_TEST_ACCEPTANCE") == "true" {
		log.Debug("implements acceptance test for ApplyDeploymentJobs")
		d, c = getTestDriverA()
		if c == nil {
			t.Fatalf("Failed to execute getTestDriver() ")
		}
		if os.Getenv("ONEVIEW_TEST_PROVISION") != "true" {
			log.Info("env ONEVIEW_TEST_PROVISION != true")
			log.Info("Skipping FreeBlade testing")
			serialNumber = d.Tc.GetTestData(d.Env, "SerialNumber").(string)
			macAddr = d.Tc.GetTestData(d.Env, "MacAddr").(string)
		} else {
			// serialNumber := d.Tc.GetTestData(d.Env, "FreeBladeSerialNumber").(string)
			serialNumber = d.Tc.GetTestData(d.Env, "FreeICSPSerialNumber").(string)
			macAddr = d.Tc.GetTestData(d.Env, "FreeMacAddr").(string)
		}
		s, err := c.GetServerBySerialNumber(serialNumber)
		assert.NoError(t, err, "GetServerBySerialNumber threw error -> %s, %+v\n", err, s)

		pubinet, err := s.GetInterface(1)
		assert.NoError(t, err, "GetInterface(1) threw error -> %s, %+v\n", err, s)
		assert.Equal(t, macAddr, pubinet.MACAddr, fmt.Sprintf("should get a valid interface -> %+v", pubinet))

		s, err = c.PreApplyDeploymentJobs(s, pubinet) // responsible for configuring the Pulbic IP CustomAttributes
		assert.NoError(t, err, "ApplyDeploymentJobs threw error -> %+v, %+v", err, s)
		s, err = s.ReloadFull(c)
		assert.NoError(t, err, "ReloadFull threw error -> %+v, %+v", err, s)

		// verify that the server attribute was saved by getting the server again and checking the value
		_, testValue2 := s.GetValueItem("public_interface", "server")
		// unmarshal the custom attribute
		var inet *icsp.Interface
		log.Debugf("public_interface value -> %+v", testValue2.Value)
		assert.NotEqual(t, "", testValue2.Value,
			fmt.Sprintf("public_interface for %s Should have a value", serialNumber))

		if testValue2.Value != "" {
			err = json.Unmarshal([]byte(testValue2.Value), &inet)
			assert.NoError(t, err, "Unmarshal Interface threw error -> %s, %+v\n", err, testValue2.Value)

			log.Infof("We got public ip addr -> %s", inet.MACAddr)
			assert.Equal(t, macAddr, inet.MACAddr, "Should return the saved custom attribute for mac address")
		}

	}
}
// TestGetInterfaces  verify that interfaces works
func TestGetInterfaces(t *testing.T) {

	var (
		d            *ICSPTest
		c            *icsp.ICSPClient
		s            icsp.Server
		serialNumber string
		err          error
	)
	if os.Getenv("ICSP_TEST_ACCEPTANCE") == "true" {
		log.Debug("implements acceptance test for TestGetInterfaces")
		d, c = getTestDriverA()
		if c == nil {
			t.Fatalf("Failed to execute getTestDriver() ")
		}
		if os.Getenv("ONEVIEW_TEST_PROVISION") == "true" {
			serialNumber = d.Tc.GetTestData(d.Env, "FreeBladeSerialNumber").(string)
			s, err = c.GetServerBySerialNumber(serialNumber)
		} else {
			serialNumber = d.Tc.GetTestData(d.Env, "SerialNumber").(string)
			s, err = c.GetServerBySerialNumber(serialNumber)
		}
		data := s.GetInterfaces()
		assert.NoError(t, err, "GetInterfaces threw error -> %s, %+v\n", err, data)
		assert.True(t, len(data) > 0, "Failed to get a valid list of interfaces -> %+v", data)
		for _, inet := range data {
			log.Infof("inet -> %+v", inet)
			log.Infof("inet ip -> %+v", inet.IPV4Addr)
			log.Infof("inet ip -> %+v", inet.Slot)
			log.Infof("inet ip -> %+v", inet.MACAddr)
		}
	} else {
		log.Debug("implements unit test for TestGetInterfaces")
		d, c = getTestDriverU()
		jsonServerData := d.Tc.GetTestData(d.Env, "ServerJSONString").(string)
		log.Debugf("jsonServerData => %s", jsonServerData)
		err := json.Unmarshal([]byte(jsonServerData), &s)
		assert.NoError(t, err, "Unmarshal Server threw error -> %s, %+v\n", err, jsonServerData)

		log.Debugf("server -> %v", s)

		data := s.GetInterfaces()
		log.Debugf("Interfaces -> %+v", data)
		assert.True(t, len(data) > 0, "Failed to get a valid list of interfaces -> %+v", data)
		for _, inet := range data {
			log.Debugf("inet -> %+v", inet)
			log.Debugf("inet ip -> %+v", inet.IPV4Addr)
			log.Debugf("inet ip -> %+v", inet.Slot)
			log.Debugf("inet ip -> %+v", inet.MACAddr)
		}
	}
}
// implement create server unt test
//TODO: This test requires a server profile to have been created
func TestCreateServer(t *testing.T) {
	var (
		d              *ICSPTest
		c              *icsp.ICSPClient
		user, pass, ip string
	)
	if os.Getenv("ICSP_TEST_ACCEPTANCE") == "true" {
		user = os.Getenv("ONEVIEW_ILO_USER")
		pass = os.Getenv("ONEVIEW_ILO_PASSWORD")
		d, c = getTestDriverA()
		if c == nil {
			t.Fatalf("Failed to execute getTestDriver() ")
		}
		ip = d.Tc.GetTestData(d.Env, "IloIPAddress").(string)
		serialNumber := d.Tc.GetTestData(d.Env, "FreeBladeSerialNumber").(string)
		log.Debug("implements acceptance test for TestCreateServer")
		s, err := c.GetServerBySerialNumber(serialNumber) // fake serial number
		assert.NoError(t, err, "GetServerBySerialNumber fake threw error -> %s, %+v\n", err, s)
		if os.Getenv("ONEVIEW_TEST_PROVISION") != "true" {
			log.Info("env ONEVIEW_TEST_PROVISION != true for TestCreateServer")
			log.Infof("Skipping test create for : %s, %s", serialNumber, ip)
			return
		}
		if s.URI.IsNil() {
			// create the server
			err := c.CreateServer(user, pass, ip, 443)
			assert.NoError(t, err, "CreateServer threw error -> %s\n", err)
		} else {
			// create the server
			err := c.CreateServer(user, pass, ip, 443)
			assert.Error(t, err, "CreateServer should throw conflict error  -> %s\n", err)
		}
		// check if the server now exist
	} else {
		_, c = getTestDriverU()
		log.Debug("implements unit test for TestCreateServer")
		err := c.CreateServer("foo", "bar", "127.0.0.1", 443)
		assert.Error(t, err, "CreateServer should throw error  -> %s\n", err)
	}
}
// TestGetInterfaceFromMac verify that getting an inerface with mac address works
func TestGetInterfaceFromMac(t *testing.T) {
	var (
		d            *ICSPTest
		c            *icsp.ICSPClient
		s            icsp.Server
		serialNumber string
		macAddr      string
		err          error
		data         icsp.Interface
	)
	if os.Getenv("ICSP_TEST_ACCEPTANCE") == "true" {
		log.Debug("implements acceptance test for TestGetInterfaceFromMac")
		d, c = getTestDriverA()
		if c == nil {
			t.Fatalf("Failed to execute getTestDriver() ")
		}
		if os.Getenv("ONEVIEW_TEST_PROVISION") == "true" {
			serialNumber = d.Tc.GetTestData(d.Env, "FreeBladeSerialNumber").(string)
			macAddr = d.Tc.GetTestData(d.Env, "FreeMacAddr").(string)
			s, err = c.GetServerBySerialNumber(serialNumber)
		} else {
			serialNumber = d.Tc.GetTestData(d.Env, "SerialNumber").(string)
			macAddr = d.Tc.GetTestData(d.Env, "MacAddr").(string)
			s, err = c.GetServerBySerialNumber(serialNumber)
		}

		s, err = c.GetServerBySerialNumber(serialNumber)
		assert.NoError(t, err, "GetServerBySerialNumber threw error -> %s, %+v\n", err, serialNumber)

		log.Debugf("server -> %v", s)
		data, err = s.GetInterfaceFromMac(macAddr)
		assert.NoError(t, err, "GetInterfaceFromMac threw error -> %s, %+v\n", err, data)
		assert.Equal(t, macAddr, data.MACAddr, "Failed to get interface -> %+v", data)
		log.Infof("Found interface -> %+v", data)
	} else {
		log.Debug("implements unit test for TestGetInterfaces")
		d, c = getTestDriverU()
		jsonServerData := d.Tc.GetTestData(d.Env, "ServerJSONString").(string)
		log.Debugf("jsonServerData => %s", jsonServerData)
		err := json.Unmarshal([]byte(jsonServerData), &s)
		assert.NoError(t, err, "Unmarshal Server threw error -> %s, %+v\n", err, jsonServerData)
		// macAddr = d.Tc.GetTestData(d.Env, "ServerMacAddr").(string)
		// TODO: find a way to unit test this
	}

}
func TestGetServerBySerialNumber(t *testing.T) {
	var (
		d *ICSPTest
		c *icsp.ICSPClient
	)
	if os.Getenv("ICSP_TEST_ACCEPTANCE") == "true" {
		d, c = getTestDriverA()
		if c == nil {
			t.Fatalf("Failed to execute getTestDriver() ")
		}
		serialNumber := d.Tc.GetTestData(d.Env, "FreeBladeSerialNumber").(string)
		data, err := c.GetServerBySerialNumber(serialNumber)
		assert.NoError(t, err, "GetServerBySerialNumber threw error -> %s, %+v\n", err, data)

		data, err = c.GetServerBySerialNumber("2M25090RMW")
		log.Infof("server -> %+v", strings.ToLower(data.Name))

		// negative test
		data, err = c.GetServerBySerialNumber("SXXXX33333") // fake serial number
		assert.NoError(t, err, "GetServerBySerialNumber fake threw error -> %s, %+v\n", err, data)
		assert.Equal(t, data.URI.String(), "null", "GetServerBySerialNumber on fake should be nil")
	}
}