package fzf

import (

"errors"
"io/ioutil"
"os"
"strings"

)

// History struct represents input history type History struct {

path     string
lines    []string
modified map[int]string
maxSize  int
cursor   int

}

// NewHistory returns the pointer to a new History struct func NewHistory(path string, maxSize int) (*History, error) {

fmtError := func(e error) error {
        if os.IsPermission(e) {
                return errors.New("permission denied: " + path)
        }
        return errors.New("invalid history file: " + e.Error())
}

// Read history file
data, err := ioutil.ReadFile(path)
if err != nil {
        // If it doesn't exist, check if we can create a file with the name
        if os.IsNotExist(err) {
                data = []byte{}
                if err := ioutil.WriteFile(path, data, 0600); err != nil {
                        return nil, fmtError(err)
                }
        } else {
                return nil, fmtError(err)
        }
}
// Split lines and limit the maximum number of lines
lines := strings.Split(strings.Trim(string(data), "\n"), "\n")
if len(lines[len(lines)-1]) > 0 {
        lines = append(lines, "")
}
return &History{
        path:     path,
        maxSize:  maxSize,
        lines:    lines,
        modified: make(map[int]string),
        cursor:   len(lines) - 1}, nil

}

func (h *History) append(line string) error {

// We don't append empty lines
if len(line) == 0 {
        return nil
}

lines := append(h.lines[:len(h.lines)-1], line)
if len(lines) > h.maxSize {
        lines = lines[len(lines)-h.maxSize:]
}
h.lines = append(lines, "")
return ioutil.WriteFile(h.path, []byte(strings.Join(h.lines, "\n")), 0600)

}

func (h *History) override(str string) {

// You can update the history but they're not written to the file
if h.cursor == len(h.lines)-1 {
        h.lines[h.cursor] = str
} else if h.cursor < len(h.lines)-1 {
        h.modified[h.cursor] = str
}

}

func (h *History) current() string {

if str, prs := h.modified[h.cursor]; prs {
        return str
}
return h.lines[h.cursor]

}

func (h *History) previous() string {

if h.cursor > 0 {
        h.cursor--
}
return h.current()

}

func (h *History) next() string {

if h.cursor < len(h.lines)-1 {
        h.cursor++
}
return h.current()

}