package core

import (
	"context"
	"errors"
	"fmt"
	"strconv"

	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/swarm"
	"github.com/docker/docker/client"
	"github.com/gianarb/orbiter/autoscaler"
	"github.com/gianarb/orbiter/provider"
)

// This function use diferent strategies to get information from
// the system itself to configure the autoloader.
// They can be environment variables for example or other systems.
func Autodetect(core *Core) error {
	autoDetectSwarmMode(core)
	if len(core.Autoscalers) == 0 {
		//return errors.New("we didn't detect any autoscaling group")
		logrus.Info("no autoscaling group detected for now")
	}
	return nil
}

func autoDetectSwarmMode(c *Core) {
	ctx := context.Background()
	dockerClient, err := client.NewEnvClient()
	if err != nil {
		logrus.WithField("error", err).Debug("Problem communication with Docker")
		return
	}
	info, err := dockerClient.Info(ctx)
	if err != nil {
		logrus.WithField("error", err).Debug("We didn't detect any Docker Swarm running")
		return
	}
	if info.Swarm.NodeID == "" {
		logrus.Debug("We didn't detect any Docker Swarm running")
		return
	}
	services, err := dockerClient.ServiceList(ctx, types.ServiceListOptions{})
	if err != nil {
		logrus.WithField("error", err).Debug("Bad comunication with Docker.")
		return
	}
	prov, _ := provider.NewSwarmProvider(map[string]string{})
	for _, service := range services {
		s, err := getAutoscalerByService(prov, service.Spec.Annotations)
		if err != nil {
			continue
		}
		c.Autoscalers[fmt.Sprintf("autoswarm/%s", service.Spec.Annotations.Name)] = s
	}
}

func getAutoscalerByService(p autoscaler.Provider, an swarm.Annotations) (autoscaler.Autoscaler, error) {
	_, e := an.Labels["orbiter"]
	if e == false {
		return autoscaler.Autoscaler{}, errors.New("")
	}
	up := convertStringLabelToInt("orbiter.up", an.Labels)
	down := convertStringLabelToInt("orbiter.down", an.Labels)
	cool := convertStringLabelToInt("orbiter.cooldown", an.Labels)
	as := autoscaler.NewAutoscaler(p, an.Name, up, down, cool)
	logrus.Infof("Registering  /handle/autoswarm/%s  to orbiter. (UP %d, DOWN %d, COOL %d)", an.Name, up, down, cool)
	return as, nil
}

func convertStringLabelToInt(labelName string, labels map[string]string) int {
	row, e := labels[labelName]
	if e == true {
		i, err := strconv.ParseInt(row, 10, 64)
		if err != nil {
			return 1
		}
		return int(i)
	}
	return 1
}
