// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.package spec

package framework

import (
	"flag"
	"fmt"
	"html/template"
	"os"
	"os/exec"
	"time"

	apierrs "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"

	"github.com/juju/errors"
	"github.com/pingcap/private-tidb-operator/pkg/client"
	"github.com/pingcap/private-tidb-operator/test/e2e/bootstrap"
)

const (
	zkPodName    = "zk-0"
	kafkaPodName = "kafka-0"
	e2eNs        = "tidb-cloud-manager-e2e"
)

var (
	cloudManagerImage string
	cloudManagerUrl   string
)

func init() {
	flag.StringVar(&cloudManagerImage, "cloud-manager-image", "", "The cloud manager image")
	flag.StringVar(&cloudManagerUrl, "cloud-manager-Url", "", "The cloud manager image")
}

type Bootstrap struct {
	Client client.Interface
}

func New() (*Bootstrap, error) {
	cli, err := client.New("")
	if err != nil {
		return nil, errors.Trace(err)
	}

	return &Bootstrap{cli}, nil
}

func (b *Bootstrap) TearDown() error {
	return nil
}

func (b *Bootstrap) Setup() error {
	return b.setupTidbCloudManger()
}

func (b *Bootstrap) setupTidbCloudManger() error {
	f, err := os.Create("/tmp/tidb-cloud-manager.yaml")
	if err != nil {
		return errors.Trace(err)
	}

	tmpl, err := template.ParseFiles("/tmp/tidb-cloud-manager.yaml.tmpl")
	if err != nil {
		return errors.Trace(err)
	}

	err = tmpl.Execute(f, struct{ Image string }{cloudManagerImage})
	if err != nil {
		return errors.Trace(err)
	}

	// Clean e2e namespace
	cmd := exec.Command("/bin/sh", "-c", fmt.Sprintf("/usr/local/bin/kubectl delete ns %s", e2eNs))
	data, err := cmd.CombinedOutput()
	if err != nil {
		Infof(string(data))
	}
	err = wait.Poll(5*time.Second, 5*time.Minute, func() (bool, error) {
		_, err = b.Client.CoreV1().Namespaces().Get(e2eNs, metav1.GetOptions{})
		if err != nil && apierrs.IsNotFound(err) {
			return true, nil
		}

		return false, nil
	})
	if err != nil {
		return err
	}

	// Delete old tidb-cloud-manager
	cmd = exec.Command("/bin/sh", "-c", "/usr/local/bin/kubectl --timeout=30s delete -f /tmp/tidb-cloud-manager.yaml")
	data, err = cmd.CombinedOutput()
	if err != nil {
		Infof(string(data))
	}
	cmd = exec.Command("/bin/sh", "-c", "/usr/local/bin/kubectl delete -f /tmp/tidb-cloud-manager-config.yaml")
	data, err = cmd.CombinedOutput()
	if err != nil {
		Infof(string(data))
	}

	err = wait.Poll(5*time.Second, 5*time.Minute, func() (bool, error) {
		_, err = b.Client.CoreV1().Namespaces().Get(bootstrap.OperatorNamespace, metav1.GetOptions{})
		if err != nil && apierrs.IsNotFound(err) {
			return true, nil
		}

		return false, nil
	})
	if err != nil {
		return err
	}

	// Create new tidb-cloud-manager
	cmd = exec.Command("/bin/sh", "-c", "/usr/local/bin/kubectl apply -f /tmp/tidb-cloud-manager.yaml")
	data, err = cmd.CombinedOutput()
	if err != nil {
		Infof(string(data))
	}
	cmd = exec.Command("/bin/sh", "-c", "/usr/local/bin/kubectl apply -f /tmp/tidb-cloud-manager-config.yaml")
	data, err = cmd.CombinedOutput()
	if err != nil {
		Infof(string(data))
	}

	return err
}
