package ec2macosinit

import (
	"encoding/json"
	"fmt"
	"os"
)

// FatalCount contains a Count for tracking the number of Fatal exits for this boot
type FatalCount struct {
	Count int `json:"count"`
}

// fatalCountFile is the file that contains the fatal counter, this is cleared on reboot
const fatalCountFile = "/tmp/.ec2-macos-init-fatal-counts.json"

// readFatalCount reads the file contents into FatalCount or returns an initialized counter.
func (r *FatalCount) readFatalCount() (err error) {
	// Check if fatal count file exists, if not, create it but leave it empty, then return 0, otherwise read and return
	_, err = os.Stat(fatalCountFile)
	if !os.IsNotExist(err) {
		err = r.readFatalFile()
		if err != nil {
			return fmt.Errorf("ec2macosinit: Failed to read %s: %s", fatalCountFile, err)
		}
	} else {
		// Take initial values for first run
		*r = FatalCount{1}
	}

	return nil
}

// IncrementFatalCount takes the current count, increments it, and saves to the temporary file.
func (r *FatalCount) IncrementFatalCount() (err error) {
	// Get the current count
	err = r.readFatalCount()
	if err != nil {
		return fmt.Errorf("ec2macosinit: unable to read run count file: %s", err)
	}

	r.Count++ // Increment the counter in the struct

	// Marshall the FatalCount struct to json
	rcBytes, err := json.Marshal(r)
	if err != nil {
		return fmt.Errorf("ec2macosinit: failed to save run counts: %s", err)
	}

	// Write the bytes to the counter file
	err = os.WriteFile(fatalCountFile, rcBytes, 0644)
	if err != nil {
		return fmt.Errorf("ec2macosinit: failed to save run counts: %s", err)
	}

	return nil
}

// readFatalFile reads the temporary file for count.
func (r *FatalCount) readFatalFile() (err error) {
	// Read the contents into bytes
	countsBytes, err := os.ReadFile(fatalCountFile)
	if err != nil {
		return fmt.Errorf("ec2macosinit: Failed to read %s: %s", fatalCountFile, err)
	}

	// Unmarshal to the struct
	err = json.Unmarshal(countsBytes, &r)
	if err != nil {
		return fmt.Errorf("ec2macosinit: Failed to parse json: %s", err)
	}

	return nil
}