// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

package config

import (
	"crypto/tls"
	"fmt"
	"net/http"
	"net/http/cookiejar"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"time"

	"github.com/gofrs/flock"
	homedir "github.com/mitchellh/go-homedir"
	ini "gopkg.in/ini.v1"
)

// Output formats
const (
	COLUMN  = "column"
	CSV     = "csv"
	JSON    = "json"
	TABLE   = "table"
	TEXT    = "text"
	DEFAULT = "default"
)

// ServerProfile describes a management server
type ServerProfile struct {
	URL       string       `ini:"url"`
	Username  string       `ini:"username"`
	Password  string       `ini:"password"`
	Domain    string       `ini:"domain"`
	APIKey    string       `ini:"apikey"`
	SecretKey string       `ini:"secretkey"`
	Client    *http.Client `ini:"-"`
}

// Core block describes common options for the CLI
type Core struct {
	Prompt       string `ini:"prompt"`
	AsyncBlock   bool   `ini:"asyncblock"`
	Timeout      int    `ini:"timeout"`
	Output       string `ini:"output"`
	VerifyCert   bool   `ini:"verifycert"`
	ProfileName  string `ini:"profile"`
	AutoComplete bool   `ini:"autocomplete"`
}

// Config describes CLI config file and default options
type Config struct {
	Dir           string
	ConfigFile    string
	HistoryFile   string
	LogFile       string
	HasShell      bool
	Core          *Core
	ActiveProfile *ServerProfile
}

func GetOutputFormats() []string {
	return []string{"column", "csv", "json", "table", "text", "default"}
}

func CheckIfValuePresent(dataset []string, element string) bool {
	for _, arg := range dataset {
		if arg == element {
			return true
		}
	}
	return false
}

// CacheFile returns the path to the cache file for a server profile
func (c Config) CacheFile() string {
	cacheDir := path.Join(c.Dir, "profiles")
	cacheFileName := "cache"
	if c.Core != nil && len(c.Core.ProfileName) > 0 {
		cacheFileName = c.Core.ProfileName + ".cache"
	}
	checkAndCreateDir(cacheDir)
	return path.Join(cacheDir, cacheFileName)
}

func hasAccess(path string) bool {
	status := true
	file, err := os.Open(path)
	if err != nil {
		status = false
	}
	file.Close()
	return status
}

func checkAndCreateDir(path string) string {
	if fileInfo, err := os.Stat(path); os.IsNotExist(err) || !fileInfo.IsDir() {
		err := os.Mkdir(path, 0700)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	}
	isAccsessible := hasAccess(path)
	if !isAccsessible {
		fmt.Println("User isn't authorized to access the config file")
		os.Exit(1)
	}
	return path
}

func getDefaultConfigDir() string {
	home, err := homedir.Dir()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	return checkAndCreateDir(path.Join(home, ".cmk"))
}

func defaultCoreConfig() Core {
	return Core{
		Prompt:       "🐱",
		AsyncBlock:   true,
		Timeout:      1800,
		Output:       JSON,
		VerifyCert:   true,
		ProfileName:  "localcloud",
		AutoComplete: true,
	}
}

func defaultProfile() ServerProfile {
	return ServerProfile{
		URL:       "http://localhost:8080/client/api",
		Username:  "admin",
		Password:  "password",
		Domain:    "/",
		APIKey:    "",
		SecretKey: "",
	}
}

func defaultConfig() *Config {
	configDir := getDefaultConfigDir()
	defaultCoreConfig := defaultCoreConfig()
	defaultProfile := defaultProfile()
	return &Config{
		Dir:           configDir,
		ConfigFile:    path.Join(configDir, "config"),
		HistoryFile:   path.Join(configDir, "history"),
		LogFile:       path.Join(configDir, "log"),
		HasShell:      false,
		Core:          &defaultCoreConfig,
		ActiveProfile: &defaultProfile,
	}
}

var profiles []string

// GetProfiles returns list of available profiles
func GetProfiles() []string {
	return profiles
}

func newHTTPClient(cfg *Config) *http.Client {
	jar, _ := cookiejar.New(nil)
	client := &http.Client{
		Jar: jar,
		Transport: &http.Transport{
			Proxy:           http.ProxyFromEnvironment,
			TLSClientConfig: &tls.Config{InsecureSkipVerify: !cfg.Core.VerifyCert},
		},
	}
	client.Timeout = time.Duration(time.Duration(cfg.Core.Timeout) * time.Second)
	return client
}

func setActiveProfile(cfg *Config, profile *ServerProfile) {
	cfg.ActiveProfile = profile
	cfg.ActiveProfile.Client = newHTTPClient(cfg)
}

func reloadConfig(cfg *Config) *Config {
	fileLock := flock.New(path.Join(getDefaultConfigDir(), "lock"))
	err := fileLock.Lock()
	if err != nil {
		fmt.Println("Failed to grab config file lock, please try again")
		return cfg
	}
	cfg = saveConfig(cfg)
	fileLock.Unlock()
	LoadCache(cfg)
	return cfg
}

func readConfig(cfg *Config) *ini.File {
	conf, err := ini.LoadSources(ini.LoadOptions{
		IgnoreInlineComment: true,
	}, cfg.ConfigFile)

	if err != nil {
		fmt.Printf("Fail to read config file: %v", err)
		os.Exit(1)
	}
	return conf
}

func saveConfig(cfg *Config) *Config {
	if _, err := os.Stat(cfg.Dir); err != nil {
		os.Mkdir(cfg.Dir, 0700)
	}

	// Save on missing config
	if _, err := os.Stat(cfg.ConfigFile); err != nil {
		defaultCoreConfig := defaultCoreConfig()
		defaultProfile := defaultProfile()
		conf := ini.Empty()
		conf.Section(ini.DEFAULT_SECTION).ReflectFrom(&defaultCoreConfig)
		conf.Section(defaultCoreConfig.ProfileName).ReflectFrom(&defaultProfile)
		conf.SaveTo(cfg.ConfigFile)
	}

	conf := readConfig(cfg)

	core, err := conf.GetSection(ini.DEFAULT_SECTION)
	if core == nil || err != nil {
		defaultCore := defaultCoreConfig()
		section, _ := conf.NewSection(ini.DEFAULT_SECTION)
		section.ReflectFrom(&defaultCore)
		cfg.Core = &defaultCore
	} else {
		// Write
		if cfg.Core != nil {
			conf.Section(ini.DEFAULT_SECTION).ReflectFrom(&cfg.Core)
		}
		// Update
		core := new(Core)
		conf.Section(ini.DEFAULT_SECTION).MapTo(core)
		if !conf.Section(ini.DEFAULT_SECTION).HasKey("autocomplete") {
			core.AutoComplete = true
		}
		cfg.Core = core
	}

	profile, err := conf.GetSection(cfg.Core.ProfileName)
	if profile == nil {
		activeProfile := defaultProfile()
		section, _ := conf.NewSection(cfg.Core.ProfileName)
		section.ReflectFrom(&activeProfile)
		setActiveProfile(cfg, &activeProfile)
	} else {
		// Write
		if cfg.ActiveProfile != nil {
			conf.Section(cfg.Core.ProfileName).ReflectFrom(&cfg.ActiveProfile)
		}
		// Update
		profile := new(ServerProfile)
		conf.Section(cfg.Core.ProfileName).MapTo(profile)
		setActiveProfile(cfg, profile)
	}
	// Save
	conf.SaveTo(cfg.ConfigFile)

	// Update available profiles list
	profiles = []string{}
	for _, profile := range conf.Sections() {
		if profile.Name() == ini.DEFAULT_SECTION {
			continue
		}
		profiles = append(profiles, profile.Name())
	}

	return cfg
}

// LoadProfile loads an existing profile
func (c *Config) LoadProfile(name string) {
	Debug("Trying to load profile: " + name)
	conf := readConfig(c)
	section, err := conf.GetSection(name)
	if err != nil || section == nil {
		fmt.Printf("Unable to load profile '%s': %v", name, err)
		os.Exit(1)
	}
	profile := new(ServerProfile)
	conf.Section(name).MapTo(profile)
	setActiveProfile(c, profile)
	c.Core.ProfileName = name
}

// UpdateConfig updates and saves config
func (c *Config) UpdateConfig(key string, value string, update bool) {
	switch key {
	case "prompt":
		c.Core.Prompt = value
	case "asyncblock":
		c.Core.AsyncBlock = value == "true"
	case "display":
		fallthrough
	case "output":
		c.Core.Output = value
	case "timeout":
		intValue, err := strconv.Atoi(value)
		if err != nil {
			fmt.Println("Error caught while setting timeout:", err)
		}
		c.Core.Timeout = intValue
	case "profile":
		c.Core.ProfileName = value
		c.ActiveProfile = nil
	case "url":
		c.ActiveProfile.URL = value
	case "username":
		c.ActiveProfile.Username = value
	case "password":
		c.ActiveProfile.Password = value
	case "domain":
		c.ActiveProfile.Domain = value
	case "apikey":
		c.ActiveProfile.APIKey = value
	case "secretkey":
		c.ActiveProfile.SecretKey = value
	case "verifycert":
		c.Core.VerifyCert = value == "true"
	case "debug":
		if value == "true" || value == "on" {
			EnableDebugging()
		} else {
			DisableDebugging()
		}
	case "autocomplete":
		c.Core.AutoComplete = value == "true"
	default:
		fmt.Println("Invalid option provided:", key)
		return
	}

	Debug("UpdateConfig key:", key, " value:", value, " update:", update)

	if update {
		reloadConfig(c)
	}
}

// NewConfig creates or reload config and loads API cache
func NewConfig(configFilePath *string) *Config {
	defaultConf := defaultConfig()
	defaultConf.Core = nil
	defaultConf.ActiveProfile = nil
	if *configFilePath != "" {
		defaultConf.ConfigFile, _ = filepath.Abs(*configFilePath)
		if _, err := os.Stat(defaultConf.ConfigFile); os.IsNotExist(err) {
			fmt.Println("Config file doesn't exist.")
			os.Exit(1)
		}
	}
	cfg := reloadConfig(defaultConf)
	LoadCache(cfg)
	return cfg
}
