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

package fetcher

import (
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"time"

	"github.com/anacrolix/torrent/metainfo"
	"github.com/dustin/go-humanize"
	"github.com/kennygrant/sanitize"
)

func createOutputDir(prefix string, forumID int) {
	path, _ := filepath.Abs(filepath.Join(prefix, strconv.Itoa(forumID)))
	if err := os.Mkdir(path, os.ModePerm); err != nil {
		dlog.Fatal().Str("путь создания", path).Err(err).Msg("Невозможно создать поддиректорию для торрент-файлов")
	}

	outputDirPath = path
}

func download(topic *forumTopic) {
	forumTopicInProgress++

	dlog.Info().Str("название топика", topic.Name).Int("количество топиков", len(forumTopics)).
		Int("номер топика", forumTopicInProgress).Msg("Скачивается топик")

	fileName, err := downloadFile(topic.Link, true)
	if err != nil {
		dlog.Error().Err(err).Str("название топика", topic.Name).Msg("Не удалось загрузить страницу топика. Пропуск")
		return
	}

	querier, err := obtainQuerier(fileName)
	if err != nil {
		dlog.Error().Err(err).Str("название топика", topic.Name).Str("ссылка на топик", topic.Link).
			Msg("Не удалось получить обработчик для страницы топика. Пропуск")
		return
	}

	lastModified := getLastModeratedDate(querier)
	if lastModified == "" {
		dlog.Warn().Str("название топика", topic.Name).Str("ссылка на топик", topic.Link).
			Msg("Топик не проверен модератором. Пропуск")
		return
	}

	downloadLink := getDownloadLink(querier)
	if downloadLink == "" {
		dlog.Warn().Str("название топика", topic.Name).Str("ссылка на топик", topic.Link).
			Msg("Не найдена ссылка для скачивания торрента. Пропуск")
		return
	}

	tempF, err := downloadFile("https://"+c.Config.URL+"/forum/"+downloadLink, false)
	if err != nil {
		dlog.Warn().Err(err).Str("название топика", topic.Name).Str("ссылка на топик", topic.Link).
			Msg("Не удалось скачать торрент-файл через несколько попыток. Пропуск")
		return
	}

	result := outputDirPath + "/" + lastModified + "-" + sanitize.BaseName(topic.Name) + ".torrent"

	err = moveFile(tempF, result)
	if err != nil {
		dlog.Warn().Err(err).Str("название топика", topic.Name).Str("ссылка на топик", topic.Link).
			Msg("Не удалось сохранить торрент-файл. Пропуск")
		return
	}

	f, _ := os.Open(result)
	defer f.Close()

	// Check downloaded torrent and get some metadata
	metadata, err := metainfo.Load(f)
	if err != nil {
		dlog.Warn().Err(err).Str("название топика", topic.Name).Str("ссылка на топик", topic.Link).
			Msg("Скачанный файл не является торрент-файлом. Пропуск")
		return
	}

	unmarshalledMetadata, _ := metadata.UnmarshalInfo()
	totalLength += unmarshalledMetadata.TotalLength()
}

func fetch(forumID int) {
	startPage := fmt.Sprintf("https://%s/forum/viewforum.php?f=%d", c.Config.URL, forumID)

	time.Sleep(5 * time.Second)

	startPageFile, err := downloadFile(startPage, true)
	if err != nil {
		dlog.Error().Err(err).Msg("Не удалось получить данные с форума")
	}

	if uberDebug {
		dlog.Info().Str("имя файла", startPageFile).Msg("Получена стартовая страница форума")
	}

	err = setQuerier(startPageFile, "forumPage", 1)
	if err != nil {
		dlog.Fatal().Err(err).Msg("Не удалось создать обработчик для страницы")
	}

	dlog.Info().Str("название форума", getForumName(forumPages[1])).Msg("Определён форум для загрузки")

	downloadAdditionalPages(forumID)

	for _, forumPage := range forumPages {
		getTopics(forumPage)
	}

	dlog.Info().Int("топиков для скачивания", len(forumTopics)).Msg("Определены все топики для скачивания")

	for _, forumTopic := range forumTopics {
		download(forumTopic)
	}
}

func printStats() {
	dlog.Info().Int("топиков обработано", len(forumTopics)).
		Str("объём раздела при полном скачивании", humanize.Bytes(uint64(totalLength))).
		Str("директория с торрент-файлами", outputDirPath).
		Msg("Работа завершена успешно. Загруженные торрент-файлы расположены в директории, указанной при старте.")
}