// NNM-Club torrent filess mass downloader
// Created for Uploaders group
// Copyright (c) 2012-2019 Vladimir "fat0troll" Hodakov

package context

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"runtime"

	"github.com/kirsle/configdir"
	"github.com/rs/zerolog"
	"gitlab.com/pztrn/flagger"
)

// getMemoryUsage returns memory usage for logger.
func (c *Context) getMemoryUsage(e *zerolog.Event, level zerolog.Level, message string) {
	var m runtime.MemStats
	runtime.ReadMemStats(&m)

	e.Str("memalloc", fmt.Sprintf("%dMB", m.Alloc/1024/1024))
	e.Str("memsys", fmt.Sprintf("%dMB", m.Sys/1024/1024))
	e.Str("numgc", fmt.Sprintf("%d", m.NumGC))
}

// initFlagger initializes flags parser
func (c *Context) initFlagger() {
	c.Flagger = flagger.New("NNM-Club Uploader Tools", flagger.LoggerInterface(log.New(os.Stdout, "", log.Lshortfile)))
	c.Flagger.Initialize()
}

func (c *Context) readConfig() {
	fh, err := os.Open(c.configFilePath)
	if err != nil {
		dlog.Fatal().Err(err).Msg("Ошибка чтения конфигурации")
	}

	defer fh.Close()

	decoder := json.NewDecoder(fh)
	err = decoder.Decode(&c.Config)
	if err != nil {
		dlog.Fatal().Err(err).Msg("Ошибка декодирования конфигурации")
	}
}

// Init is an initialization function for core context
// Without these parts of the application we can't start at all
func (c *Context) Init() {
	c.initFlagger()

	c.Logger = zerolog.New(zerolog.ConsoleWriter{Out: os.Stdout}).With().Timestamp().Logger()
	c.Logger = c.Logger.Hook(zerolog.HookFunc(c.getMemoryUsage))

	dlog = c.Logger.With().Str("модуль", "context").Logger()
}

func (c *Context) InitConfig() {
	configPath := configdir.LocalConfig("uploader_tools")
	err := configdir.MakePath(configPath)
	if err != nil {
		dlog.Fatal().Err(err).Str("директория с конфигурационным файлом", configPath).Msg("Не получилось создать или обнаружить директорию для конфигурационных файлов")
	}

	dlog.Debug().Str("директория с конфигурационным файлом", configPath).Msg("Найдена директория с конфигурационным файлом")

	configFile := filepath.Join(configPath, "settings.json")
	c.configFilePath = configFile

	if _, err = os.Stat(configFile); os.IsNotExist(err) {
		// Generating new config on first run
		dlog.Debug().Msg("Генерируется новый конфигурационный файл")

		c.SaveConfig()
	} else {
		dlog.Debug().Msg("Используется существующий конфигурационный файл")

		c.readConfig()
	}
}

func (c *Context) SaveConfig() {
	fh, err := os.Create(c.configFilePath)
	if err != nil {
		dlog.Fatal().Err(err).Msg("Не удалось создать файл конфигурации")
	}
	defer fh.Close()

	encoder := json.NewEncoder(fh)
	err = encoder.Encode(&c.Config)
	if err != nil {
		dlog.Fatal().Err(err).Msg("Не удалось записать файл конфигурации")
	}
}

func (c *Context) SetCookies(cookies []*http.Cookie) {
	c.Cookies = append(c.Cookies, cookies...)
}