package main

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io"
	"net/url"
	"sort"
	"strings"

	"github.com/n0x1m/md2gmi/mdproc"
	"github.com/n0x1m/md2gmi/pipe"
)

func source(r io.Reader) pipe.Source {
	return func() chan pipe.StreamItem {
		data := make(chan pipe.StreamItem)
		s := bufio.NewScanner(r)

		go func() {
			i := 0

			for s.Scan() {
				data <- pipe.NewItem(i, s.Bytes())
				i++
			}
			close(data)
		}()

		return data
	}
}

func sink(w *bytes.Buffer) pipe.Sink {
	return func(dest chan pipe.StreamItem) {
		for b := range dest {
			_, err := fmt.Fprintf(w, string(b.Payload()))
			if err != nil {
				fmt.Println(err)
			}

		}
	}
}

func (fileContent *FileContent) FormatContent() string {
	content := fileContent.Content
	badChars := make(map[string]string)
	badChars["ā"] = "ā"
	badChars["ē"] = "ē"
	badChars["ī"] = "ī"
	badChars["ō"] = "ō"
	badChars["ū"] = "ū"
	for k, v := range badChars {
		content = strings.ReplaceAll(content, k, v)
	}

	var writer bytes.Buffer
	s := pipe.New()
	s.Use(mdproc.Preprocessor())
	s.Use(mdproc.FormatLinks)
	s.Handle(source(strings.NewReader(content)), sink(&writer))

	return writer.String()
}

func (file *TreeFile) CategoriesAsUrl() string {
	escapedCategories := []string{}
	for _, c := range file.Category {
		escapedCategories = append(escapedCategories, url.QueryEscape(c))
	}

	return strings.Join(escapedCategories, "/")
}

func (file *TreeFile) GmiName() string {
	return strings.Replace(file.Name, ".md", ".gmi", 1)
}

func (file *TreeFile) CategoryPath() string {
	return "/" + strings.Join(file.Category, "/")
}

func (tree *Tree) GetIndexFile() (*TreeFile, error) {
	for _, file := range tree.RootFiles {
		if file.Name == "index.md" {
			return file, nil
		}
	}

	return nil, errors.New("index file not found")
}

func GetLastFiles(files []*TreeFile) []*TreeFile {
	sortingFiles := make(map[string]*TreeFile)
	for _, f := range files {
		sortingFiles[f.Id] = f
	}

	keys := make([]string, 0, len(sortingFiles))
	for k := range sortingFiles {
		keys = append(keys, k)
	}
	sort.Sort(sort.Reverse(sort.StringSlice(keys)))

	length := 10
	if len(keys) < 10 {
		length = len(keys)
	}
	lastFiles := make([]*TreeFile, 0, length)
	for i, k := range keys {
		if i == length {
			break
		}

		lastFiles = append(lastFiles, sortingFiles[k])
	}

	return lastFiles
}