package hooks_test

import (
	"bytes"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/cloudfoundry/go-buildpack/src/go/hooks"
	"github.com/cloudfoundry/libbuildpack"
	"github.com/cloudfoundry/libbuildpack/ansicleaner"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

func createFile(dir, filename, command string, perm os.FileMode) error {
	procFile := filepath.Join(dir, filename)
	f, err := os.OpenFile(procFile, os.O_CREATE|os.O_WRONLY, perm)
	if err != nil {
		return err
	}

	defer f.Close()

	if _, err = f.WriteString(command); err != nil {
		return err
	}
	return nil
}

var _ = Describe("Appdynamics", func() {
	var (
		err         error
		buildDir    string
		depsDir     string
		stager      *libbuildpack.Stager
		buffer      *bytes.Buffer
		appdynamics hooks.AppdynamicsHook
	)

	BeforeEach(func() {
		buildDir, err = ioutil.TempDir("", "go-buildpack.build.")
		Expect(err).To(BeNil())

		depsDir, err = ioutil.TempDir("", "go-buildpack.deps.")
		Expect(err).To(BeNil())

		buffer = new(bytes.Buffer)
		logger := libbuildpack.NewLogger(ansicleaner.New(buffer))

		args := []string{buildDir, "", depsDir, "9"}
		stager = libbuildpack.NewStager(args, logger, &libbuildpack.Manifest{})

		command := &libbuildpack.Command{}

		appdynamics = hooks.AppdynamicsHook{
			Log:     logger,
			Command: command,
		}
	})

	AfterEach(func() {
		Expect(os.RemoveAll(buildDir)).To(Succeed())
	})

	Context("GenerateAppdynamicsScript", func() {
		It("Generates script from Env map", func() {
			envVal := map[string]string{
				"APPD_KEY_1": "APPD_VAL_1",
				"APPD_KEY_2": "APPD_VAL_2",
			}
			script := appdynamics.GenerateAppdynamicsScript(envVal)
			expectedScript := `# Autogenerated Appdynamics Script 

export APPD_KEY_1=APPD_VAL_1
export APPD_KEY_2=APPD_VAL_2`
			Expect(script).To(Equal(expectedScript))
		})
	})

	Context("CreateAppDynamicsEnv", func() {
		It("Generates script from Env map", func() {
			envVal := map[string]string{
				"APPD_KEY_1": "APPD_VAL_1",
				"APPD_KEY_2": "APPD_VAL_2",
			}
			appdynamics.CreateAppDynamicsEnv(stager, envVal)
			appdynamicsShellScript := filepath.Join(stager.DepDir(), "profile.d", "appdynamics.sh")
			Expect(libbuildpack.FileExists(appdynamicsShellScript)).To(BeTrue())
			expectedScript := `# Autogenerated Appdynamics Script 

export APPD_KEY_1=APPD_VAL_1
export APPD_KEY_2=APPD_VAL_2`
			script, err := ioutil.ReadFile(appdynamicsShellScript)
			Expect(err).To(BeNil())
			Expect(string(script)).To(Equal(expectedScript))
		})
	})

	Context("BeforeCompile when VCAP_SERVICES is not present", func() {
		BeforeEach(func() {
			Expect(os.Getenv("VCAP_SERVICES")).To(Equal(""))
		})

		It("VCAP_SERVICES is not present", func() {
			err := appdynamics.BeforeCompile(stager)
			Expect(err).To(BeNil())
			Expect(libbuildpack.FileExists(filepath.Join(stager.DepDir(), "profile.d", "appdynamics.sh"))).To(BeFalse())
		})
	})

	Context("BeforeCompile when VCAP_SERVICES has no appdynamics", func() {
		BeforeEach(func() {
			Expect(os.Getenv("VCAP_SERVICES")).To(Equal(""))
			os.Setenv("VCAP_SERVICES", `{"service": [{"credentials": {"login": "name"}, "name": "443"}]}`)
		})

		AfterEach(func() {
			os.Unsetenv("VCAP_SERVICES")
		})

		It("VCAP_SERVICES has no appdynamics", func() {
			err := appdynamics.BeforeCompile(stager)
			Expect(err).To(BeNil())
			Expect(libbuildpack.FileExists(filepath.Join(stager.DepDir(), "profile.d", "appdynamics.sh"))).To(BeFalse())
		})
	})

	Context("BeforeCompile when VCAP_SERVICES has appdynamics", func() {
		BeforeEach(func() {
			os.Setenv("VCAP_SERVICES",
				`{"appdynamics": [{"instance_name": "plan-instance", "tags": [], "name": "plan", "syslog_drain_url": null, "binding_name": null, "credentials": {"host-name": "controller.test.com", "plan-name": "plan", "guid": "guid", "plan-description": "plan", "ssl-enabled": false, "account-access-key": "key", "account-name": "account-name", "port": "7777"}, "label": "appdynamics"}]}`)
			os.Setenv("VCAP_APPLICATION", `{"application_id": "applicationId", "name": "test",  "application_name": "test"}`)
			os.Setenv("APPD_TIER_NAME", "tier")
			os.Setenv("APPD_NODE_NAME", "node")
		})

		AfterEach(func() {
			os.Unsetenv("VCAP_SERVICES")
		})

		It("VCAP_SERVICES has appdynamics", func() {
			err := appdynamics.BeforeCompile(stager)
			Expect(err).To(BeNil())

			Expect(libbuildpack.FileExists(filepath.Join(stager.DepDir(), "profile.d", "appdynamics.sh"))).To(BeTrue())
			appdynamicsInfo, err := ioutil.ReadFile(filepath.Join(stager.DepDir(), "profile.d", "appdynamics.sh"))
			expectedInfo := `# Autogenerated Appdynamics Script 

export APPD_ACCOUNT_ACCESS_KEY=key
export APPD_ACCOUNT_NAME=account-name
export APPD_APP_NAME=test
export APPD_CONTROLLER_HOST=controller.test.com
export APPD_CONTROLLER_PORT=7777
export APPD_NODE_NAME=node
export APPD_SSL_ENABLED=off
export APPD_TIER_NAME=tier`

			Expect(string(appdynamicsInfo)).To(Equal(expectedInfo))
			Expect(err).To(BeNil())
		})
	})
})
