// +build acceptance

package openstack

import (
	"crypto/rand"
	"fmt"
	"github.com/rackspace/gophercloud/openstack/compute/servers"
	"github.com/rackspace/gophercloud/openstack/identity"
	"github.com/rackspace/gophercloud/openstack/utils"
	"os"
	"text/tabwriter"
	"time"
)

var errTimeout = fmt.Errorf("Timeout.")

type testState struct {
	o             identity.AuthOptions
	a             identity.AuthResults
	sc            *identity.ServiceCatalog
	eps           []identity.Endpoint
	w             *tabwriter.Writer
	imageId       string
	flavorId      string
	region        string
	ep            string
	client        *servers.Client
	createdServer *servers.Server
	gottenServer  *servers.Server
	updatedServer *servers.Server
	serverName    string
	alternateName string
}

func setupForList() (*testState, error) {
	var err error

	ts := new(testState)

	ts.o, err = utils.AuthOptions()
	if err != nil {
		return ts, err
	}

	ts.a, err = identity.Authenticate(ts.o)
	if err != nil {
		return ts, err
	}

	ts.sc, err = identity.GetServiceCatalog(ts.a)
	if err != nil {
		return ts, err
	}

	ts.eps, err = findAllComputeEndpoints(ts.sc)
	if err != nil {
		return ts, err
	}

	ts.w = new(tabwriter.Writer)
	ts.w.Init(os.Stdout, 2, 8, 2, ' ', 0)

	return ts, nil
}

func setupForCRUD() (*testState, error) {
	ts, err := setupForList()
	if err != nil {
		return ts, err
	}

	ts.imageId = os.Getenv("OS_IMAGE_ID")
	if ts.imageId == "" {
		return ts, fmt.Errorf("Expected OS_IMAGE_ID environment variable to be set")
	}

	ts.flavorId = os.Getenv("OS_FLAVOR_ID")
	if ts.flavorId == "" {
		return ts, fmt.Errorf("Expected OS_FLAVOR_ID environment variable to be set")
	}

	ts.region = os.Getenv("OS_REGION_NAME")
	if ts.region == "" {
		ts.region = ts.eps[0].Region
	}

	ts.ep, err = findEndpointForRegion(ts.eps, ts.region)
	if err != nil {
		return ts, err
	}

	return ts, err
}

func findAllComputeEndpoints(sc *identity.ServiceCatalog) ([]identity.Endpoint, error) {
	ces, err := sc.CatalogEntries()
	if err != nil {
		return nil, err
	}

	for _, ce := range ces {
		if ce.Type == "compute" {
			return ce.Endpoints, nil
		}
	}

	return nil, fmt.Errorf("Compute endpoint not found.")
}

func findEndpointForRegion(eps []identity.Endpoint, r string) (string, error) {
	for _, ep := range eps {
		if ep.Region == r {
			return ep.PublicURL, nil
		}
	}
	return "", fmt.Errorf("Unknown region %s", r)
}

func countDown(ts *testState, timeout int) (bool, int, error) {
	if timeout < 1 {
		return false, 0, errTimeout
	}
	time.Sleep(1 * time.Second)
	timeout--

	gr, err := servers.GetDetail(ts.client, ts.createdServer.Id)
	if err != nil {
		return false, timeout, err
	}

	ts.gottenServer, err = servers.GetServer(gr)
	if err != nil {
		return false, timeout, err
	}

	return true, timeout, nil
}

func createServer(ts *testState) error {
	ts.serverName = randomString("ACPTTEST", 16)
	fmt.Printf("Attempting to create server: %s\n", ts.serverName)

	ts.client = servers.NewClient(ts.ep, ts.a, ts.o)

	cr, err := servers.Create(ts.client, map[string]interface{}{
		"flavorRef": ts.flavorId,
		"imageRef":  ts.imageId,
		"name":      ts.serverName,
	})
	if err != nil {
		return err
	}

	ts.createdServer, err = servers.GetServer(cr)
	return err
}

func waitForStatus(ts *testState, s string) error {
	var (
		inProgress bool
		timeout    int
		err        error
	)

	for inProgress, timeout, err = countDown(ts, 300); inProgress; inProgress, timeout, err = countDown(ts, timeout) {
		if ts.gottenServer.Id != ts.createdServer.Id {
			return fmt.Errorf("created server id (%s) != gotten server id (%s)", ts.createdServer.Id, ts.gottenServer.Id)
		}

		if ts.gottenServer.Status == s {
			fmt.Printf("Server reached state %s after %d seconds (approximately)\n", s, 300-timeout)
			break
		}
	}

	if err == errTimeout {
		fmt.Printf("Time out -- I'm not waiting around.\n")
		err = nil
	}

	return err
}

func changeServerName(ts *testState) error {
	var (
		inProgress bool
		timeout    int
	)

	ts.alternateName = randomString("ACPTTEST", 16)
	for ts.alternateName == ts.serverName {
		ts.alternateName = randomString("ACPTTEST", 16)
	}
	fmt.Println("Attempting to change server name")

	ur, err := servers.Update(ts.client, ts.createdServer.Id, map[string]interface{}{
		"name": ts.alternateName,
	})
	if err != nil {
		return err
	}

	ts.updatedServer, err = servers.GetServer(ur)
	if err != nil {
		return err
	}

	if ts.updatedServer.Id != ts.createdServer.Id {
		return fmt.Errorf("Expected updated and created server to share the same ID")
	}

	for inProgress, timeout, err = countDown(ts, 300); inProgress; inProgress, timeout, err = countDown(ts, timeout) {
		if ts.gottenServer.Id != ts.updatedServer.Id {
			return fmt.Errorf("Updated server ID (%s) != gotten server ID (%s)", ts.updatedServer.Id, ts.gottenServer.Id)
		}

		if ts.gottenServer.Name == ts.alternateName {
			fmt.Printf("Server updated after %d seconds (approximately)\n", 300-timeout)
			break
		}
	}

	if err == errTimeout {
		fmt.Printf("I'm not waiting around.\n")
		err = nil
	}

	return err
}

func changeAdminPassword(ts *testState) error {
	fmt.Println("Current password: "+ts.createdServer.AdminPass)
	randomPassword := randomString("", 16)
	for randomPassword == ts.createdServer.AdminPass {
		randomPassword = randomString("", 16)
	}
	fmt.Println("    New password: "+randomPassword)
	
	err := servers.ChangeAdminPassword(ts.client, ts.createdServer.Id, randomPassword)
	if err != nil {
		return err
	}
	
	err = waitForStatus(ts, "PASSWORD")
	if err != nil {
		return err
	}
	
	return waitForStatus(ts, "ACTIVE")
}

func rebootServer(ts *testState) error {
	fmt.Println("Attempting reboot of server "+ts.createdServer.Id)
	err := servers.Reboot(ts.client, ts.createdServer.Id, servers.OSReboot)
	if err != nil {
		return err
	}
	
	err = waitForStatus(ts, "REBOOT")
	if err != nil {
		return err
	}
	
	return waitForStatus(ts, "ACTIVE")
}

// randomString generates a string of given length, but random content.
// All content will be within the ASCII graphic character set.
// (Implementation from Even Shaw's contribution on
// http://stackoverflow.com/questions/12771930/what-is-the-fastest-way-to-generate-a-long-random-string-in-go).
func randomString(prefix string, n int) string {
	const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	var bytes = make([]byte, n)
	rand.Read(bytes)
	for i, b := range bytes {
		bytes[i] = alphanum[b%byte(len(alphanum))]
	}
	return prefix + string(bytes)
}
