// 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 v1

import (
	"strings"

	"time"

	"github.com/pingcap/tidb-operator/pkg/util/label"
	"k8s.io/api/core/v1"
	podutil "k8s.io/kubernetes/pkg/api/v1/pod"
)

const (
	startedWaitDuration = 10 * time.Second
)

// IsReady returns whether the pod is running and is ready in PD cluster
func (ts *TidbSet) IsReady(pod *v1.Pod) bool {
	if pod.Status.Phase != v1.PodRunning {
		return false
	}

	for _, cs := range pod.Status.ContainerStatuses {
		running := cs.State.Running
		if running == nil {
			return false
		}

		if running.StartedAt.Add(startedWaitDuration).After(time.Now()) {
			return false
		}
	}

	if !podutil.IsPodReady(pod) {
		return false
	}

	if strings.HasSuffix(ts.Name, "-pdset") {
		return ts.isPDReady(pod)
	}

	if strings.HasSuffix(ts.Name, "-tidbset") {
		return ts.isTiDBReady(pod)
	}

	if strings.HasSuffix(ts.Name, "-tikvset") {
		return ts.isTiKVReady(pod)
	}

	return false
}

func (ts *TidbSet) isPDReady(pod *v1.Pod) bool {
	if ps, ok := ts.Status.PDStatus[pod.GetName()]; ok {
		if ps.ID != "" {
			return true
		}
	}

	return false
}

func (ts *TidbSet) isTiDBReady(pod *v1.Pod) bool {
	if tids, ok := ts.Status.TiDBStatus[pod.GetName()]; ok {
		if tids.IP != "" {
			return true
		}
	}

	return false
}

func (ts *TidbSet) isTiKVReady(pod *v1.Pod) bool {
	if tiks, ok := ts.Status.TiKVStatus[pod.GetName()]; ok {
		if tiks.State == TiKVStateUp {
			return true
		}
	}

	return false
}

// Paused predicates whether TidbSet is paused
func (ts *TidbSet) Paused() bool {
	if ts.Annotations == nil {
		return false
	}

	if paused, ok := ts.Annotations[label.AnnPaused]; ok {
		return paused == "true"
	}

	return false
}

// ImageFor returns the image of the container type
func (ts *TidbSet) ImageFor(ctype ContainerType) string {
	var image string
	for _, c := range ts.Spec.Template.Spec.Containers {
		if c.Name == ctype.String() {
			return c.Image
		}
	}
	return image
}
