package main

import (
	"flag"
	"fmt"
	"io/fs"
	"os"
	"strconv"

	"github.com/fatih/color"
)

func usage() {
	fmt.Fprintf(os.Stderr, "Usage:\n")
	os.Exit(1)
}

func formatFileSize(fi fs.FileInfo) (size string) {
	switch fileSizeFloat := float64(fi.Size()); {

	case fileSizeFloat > (1024 * 1024 * 1024): //GB
		fileSizeFloat /= (1024 * 1024 * 1024)
		size = strconv.FormatFloat(fileSizeFloat, 'f', 1, 64)
		return size + "G"

	case fileSizeFloat > (1024 * 1024): //MB
		fileSizeFloat /= (1024 * 1024)
		size = strconv.FormatFloat(fileSizeFloat, 'f', 1, 64)
		return size + "M"

	case fileSizeFloat > 1024: //KB
		fileSizeFloat /= 1024
		size = strconv.FormatFloat(fileSizeFloat, 'f', 1, 64)
		return size + "K"

	case fileSizeFloat > 0: //B
		size = strconv.FormatFloat(fileSizeFloat, 'f', 0, 64)
		return size

	default:
		return "0"
	}
}

func getFileMod(fi fs.FileInfo) (mod string) {
	//day month short time HH:MM
	day := strconv.Itoa(fi.ModTime().Day())
	month := fi.ModTime().Month().String()
	timeH := strconv.Itoa(fi.ModTime().Hour())
	timeM := strconv.Itoa(fi.ModTime().Minute())
	if len(timeH) <= 1 {
		timeH = "0" + timeH
	}
	if len(timeM) <= 1 {
		timeM = "0" + timeM
	}

	mod = day + " " + month[0:3] + " " + timeH + ":" + timeM
	return mod
}

func PrintHeaders() {
	headersOutput := color.New(color.FgHiBlack).Add(color.Underline)
	//headersOutput.Printf("%-10s %7s %5s %11s\n", "Type", "Size", "Time", "Name") //leave this
	headersOutput.Printf("%-10s ", "Type")
	headersOutput.Printf("%7s ", "Size")
	headersOutput.Printf("%5s ", "Time")
	headersOutput.Printf("%11s\n", "Name")
}

func main() {
	var flagNoColor = flag.Bool("no-colour", false, "Disable color output")
	var flagNoList = flag.Bool("no-l", false, "Disable ls -l output")
	var dir string

	flag.Parse()

	if *flagNoColor {
		color.NoColor = true
	}

	dirOutput := color.New(color.FgCyan, color.Bold)
	fileOutput := color.New(color.FgWhite, color.Bold)

	if len(os.Args) == 1 {
		dir = "."
	} else {
		dir = os.Args[1]
	}

	files, err := os.ReadDir(dir)

	if err != nil {
		usage()
	}
	if !*flagNoList {
		PrintHeaders()
	}

	for _, file := range files {
		fileName := file.Name()
		fileType := file.Type()
		dirSize := "-"
		fileSize := ""
		fileModTime := ""

		fi, err := os.Stat(fileName)
		if err != nil {
			usage()
		}
		fileSize = formatFileSize(fi)
		fileModTime = getFileMod(fi)

		if !*flagNoList {
			if file.IsDir() {
				dirOutput.Printf("%s %7s %7s\t%s\n", fileType, dirSize, fileModTime, fileName) //leave this
			} else {
				fmt.Printf("%7s %7s %4s", fileType, fileSize, fileModTime)
				fileOutput.Printf("\t%s\n", fileName)
			}
		} else {
			if file.IsDir() {
				dirOutput.Printf("%s\n", fileName)
			} else {
				fileOutput.Printf("%s\n", fileName)
			}
		}

	}
}
