package main

import (
	"fmt"
	"github.com/spf13/cobra"
	"os"
)

type Options struct {
	cni        string
	policyType string
}

func readConfig(files []string) (*Config, error) {
	config := &Config{}
	for _, file := range files {
		fmt.Fprintf(os.Stderr, "Reading %s\n", file)
		configNew, err := LoadConfig(file)
		if err != nil {
			return nil, fmt.Errorf("%s: %w", file, err)
		}
		config.Update(configNew)
	}
	err := config.Validate()
	if err != nil {
		return nil, fmt.Errorf("Error loading configuration: %w", err)
	}
	return config, nil
}

func generateNetworkPolicy(files []string, options *Options) error {
	if len(files) == 0 {
		return fmt.Errorf("File expected")
	}
	config, err := readConfig(files)
	if err != nil {
		return err
	}

	policyTemplates, err := NewPolicyTemplates()
	if err != nil {
		return err
	}
	var generator Generator
	generator = NetworkPolicyGenerrator{
		config:          config,
		policyTemplates: policyTemplates,
	}
	err = Generate(os.Stdout, generator, config)
	if err != nil {
		return err
	}

	return nil
}

func generateLinkerdPolicies(files []string, options *Options) error {
	return fmt.Errorf(("Not yet implemented"))
}

func main() {

	options := Options{
		cni:        "cilium",
		policyType: "netpol",
	}
	cmd := &cobra.Command{
		Use:   "policygen",
		Short: "Defining policies to enforce topology using network policies and service meshes",
		Long:  "Defining policies to enforce topology using network policies and service meshes",
	}

	generate := &cobra.Command{
		Use:   "generate",
		Short: "Generate configuration",
		Long:  "Generate configuration",
	}
	cmd.AddCommand(generate)

	netpol := &cobra.Command{
		Use:   "netpol",
		Short: "Generate NetworkPolicyp",
		Long:  "Generate NetworkPolicy",
		RunE: func(cmd *cobra.Command, args []string) error {
			return generateNetworkPolicy(args, &options)
		},
	}
	generate.AddCommand(netpol)

	linkerd := &cobra.Command{
		Use:   "linkerd",
		Short: "Generate linkerd authorization policies",
		Long:  "Generate linkerd authorization policies",
		RunE: func(cmd *cobra.Command, args []string) error {
			return generateLinkerdPolicies(args, &options)
		},
	}
	generate.AddCommand(linkerd)

	validate := &cobra.Command{
		Use:   "validate",
		Short: "Validate configuration",
		Long:  "Validate configuration",
		RunE: func(cmd *cobra.Command, args []string) error {
			return validate(args, &options)
		},
	}
	cmd.AddCommand(validate)

	err := cmd.Execute()
	if err != nil {
		os.Exit(1)
	}
}