package history

import (
	
	
	
	
	
	
	
)

var (
	errOpenHistoryFile = errors.New("failed to open history file")
	errNegativeIndex   = errors.New("cannot use a negative index when requesting historic commands")
	errOutOfRangeIndex = errors.New("index requested greater than number of items in history")
)

// fileHistory provides a history source based on a file.
type fileHistory struct {
	file  string
	lines []Item
}

// Item is the structure of an individual item in the History.list slice.
type Item struct {
	Index    int
	DateTime time.Time
	Block    string
}

// NewSourceFromFile returns a new history source writing to and reading from a file.
func ( string) (Source, error) {
	var  error

	 := new(fileHistory)
	.file = 
	.lines,  = openHist()

	return , 
}

func openHist( string) ( []Item,  error) {
	,  := os.Open()
	if  != nil {
		return , fmt.Errorf("%w: %s", errOpenHistoryFile, .Error())
	}

	 := bufio.NewScanner()
	for .Scan() {
		var  Item

		 := json.Unmarshal(.Bytes(), &)
		if  != nil || len(.Block) == 0 {
			continue
		}

		.Index = len()
		 = append(, )
	}

	.Close()

	return , nil
}

// Write item to history file.
func ( *fileHistory) ( string) (int, error) {
	 := strings.TrimSpace()
	if  == "" {
		return 0, nil
	}

	 := Item{
		DateTime: time.Now(),
		Block:    ,
		Index:    len(.lines),
	}

	if len(.lines) == 0 || .lines[len(.lines)-1].Block !=  {
		.lines = append(.lines, )
	}

	 := struct {
		 time.Time `json:"datetime"`
		    string    `json:"block"`
	}{
		:    ,
		: .DateTime,
	}

	,  := json.Marshal()
	if  != nil {
		return .Len(), 
	}

	,  := os.OpenFile(.file, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o600)
	if  != nil {
		return 0, fmt.Errorf("%w: %s", errOpenHistoryFile, .Error())
	}

	_,  = .Write(append(, '\n'))
	.Close()

	return .Len(), 
}

// GetLine returns a specific line from the history file.
func ( *fileHistory) ( int) (string, error) {
	if  < 0 {
		return "", errNegativeIndex
	}

	if  < len(.lines) {
		return .lines[].Block, nil
	}

	return "", errOutOfRangeIndex
}

// Len returns the number of items in the history file.
func ( *fileHistory) () int {
	return len(.lines)
}

// Dump returns the entire history file.
func ( *fileHistory) () interface{} {
	return .lines
}