package status

import (
	"fmt"
)

type Status int

const (
	StatusNoStatus Status = iota
	StatusNotFound
	StatusPending
	StatusProcessing
	StatusSuccess
	StatusFailure
)

func IsStatusTerminal(s Status) bool {
	return s == StatusSuccess || s == StatusFailure
}

func StatusString(s Status) string {
	switch s {
	case StatusNoStatus:
		return "no_status"
	case StatusNotFound:
		return "not_found"
	case StatusPending:
		return "pending"
	case StatusProcessing:
		return "processing"
	case StatusSuccess:
		return "success"
	case StatusFailure:
		return "failure"
	default:
		panic("MUST NOT REACH!")
	}
}

type ResourceType int

const (
	ResourceHelmRelease ResourceType = iota
	ResourceIngress
)

type ResourceRef struct {
	Id        string
	Name      string
	Namespace string
}

type Resource struct {
	ResourceRef
	Type ResourceType
}

type Monitor interface {
	Get(r Resource) (Status, error)
}

type ResourceMonitor interface {
	Get(r ResourceRef) (Status, error)
}

type delegatingMonitor struct {
	m map[ResourceType]ResourceMonitor
}

func NewDelegatingMonitor(kubeconfig string) (Monitor, error) {
	helm, err := NewHelmReleaseMonitor(kubeconfig)
	if err != nil {
		return nil, err
	}
	ingress, err := NewIngressMonitor(kubeconfig)
	if err != nil {
		return nil, err
	}
	return delegatingMonitor{
		map[ResourceType]ResourceMonitor{
			ResourceHelmRelease: helm,
			ResourceIngress:     ingress,
		},
	}, nil
}

func (m delegatingMonitor) Get(r Resource) (Status, error) {
	if rm, ok := m.m[r.Type]; !ok {
		return StatusNoStatus, fmt.Errorf("unknown resource type: %d", r.Type)
	} else {
		return rm.Get(r.ResourceRef)
	}
}
