/*
ArOZ Online System - fscov File Naming Format Conversion Tool

This micro-servie is designed to convert filename from and to umfilename (ArOZ Online System File Explorer Custom Format)
and standard UTF-8 File System filename.

Usage:
./fsconv
(Convert all the files, folder and sub-directories from and to umfilename to UTF8 filename.)

./fsconv {target} {mode (um / utf)}
(Convert all the files, folder and sub-directories to filename in given mode, target can be file or directory.)

*/

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"reflect"
	"strconv"
	"sort"
	"regexp"
	"strings"
	"encoding/hex"
)

//Commonly used functions
func in_array(val interface{}, array interface{}) (exists bool, index int) {
	exists = false
	index = -1

	switch reflect.TypeOf(array).Kind() {
	case reflect.Slice:
		s := reflect.ValueOf(array)

		for i := 0; i < s.Len(); i++ {
			if reflect.DeepEqual(val, s.Index(i).Interface()) == true {
				index = i
				exists = true
				return
			}
		}
	}

	return
}

func file_exists(path string) bool {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return false
	}
	return true
}

func file_get_contents(path string) string {
	dat, err := ioutil.ReadFile(path)
	if err != nil {
		panic("Unable to read file: " + path)
	}
	return (string(dat))

}

func scan_recursive(dir_path string, ignore []string) ([]string, []string) {

	folders := []string{}
	files := []string{}

	// Scan
	filepath.Walk(dir_path, func(path string, f os.FileInfo, err error) error {

		_continue := false

		// Loop : Ignore Files & Folders
		for _, i := range ignore {

			// If ignored path
			if strings.Index(path, i) != -1 {

				// Continue
				_continue = true
			}
		}

		if _continue == false {

			f, err = os.Stat(path)

			// If no error
			if err != nil {
				panic("ERROR. " + err.Error())
			}

			// File & Folder Mode
			f_mode := f.Mode()

			// Is folder
			if f_mode.IsDir() {

				// Append to Folders Array
				folders = append(folders, path)

				// Is file
			} else if f_mode.IsRegular() {

				// Append to Files Array
				files = append(files, path)
			}
		}

		return nil
	})

	return folders, files
}

func hex2bin(s string) []byte {
	ret, _ := hex.DecodeString(s)
	return ret
}

func Bin2hex(str string) (string, error) {
	i, err := strconv.ParseInt(str, 2, 0)
	if err != nil {
		return "", err
	}
	return strconv.FormatInt(i, 16), nil
}

type ByLen []string
 
func (a ByLen) Len() int {
   return len(a)
}
 
func (a ByLen) Less(i, j int) bool {
   return len(a[i]) > len(a[j])
}
 
func (a ByLen) Swap(i, j int) {
   a[i], a[j] = a[j], a[i]
}
 

func main() {
	dir, _ := filepath.Abs(filepath.Dir(os.Args[0]))
	if len(os.Args) < 2 {
		//Default options, usually double click will start this process
		folders, files := scan_recursive(dir, []string{os.Args[0]})
		for i := 0; i < len(files); i++ {
			thisFilepath := strings.ReplaceAll(files[i], "\\", "/")
			filename := path.Base(thisFilepath)
			extension := filepath.Ext(filename)
			name := filename[0 : len(filename)-len(extension)]
			//Check if it has the inith prefix
			if len(name) > 5 && name[0:5] == "inith"{
				//This is hex filename. Translate its name to normal filename
				originalName := string(hex2bin(name[5:]))
				var re = regexp.MustCompile(`/[/\\?%*:|"<>]/g`)
				safeName := re.ReplaceAllString(originalName, `-`)
				fmt.Println(filename + " -> " + safeName + extension)
				err := os.Rename(files[i], path.Dir(thisFilepath) + "/" + safeName + extension)
				if (err != nil){
					panic(err)
				}
			}
			
		}
		
		//Sort the array of folders by string length, hence deeper folder will be renamed first
		sort.Sort(ByLen(folders))
		for j := 0; j < len(folders); j++{
			foldername := path.Base(folders[j])
			fmt.Println(foldername)
		}


	}else if (len(os.Args) == 2 && os.Args[1] == "help"){
		//Show help message
		fmt.Println("ArOZ Online UM File Naming Method Converter")
		fmt.Println("Usage: \n ./fsconv		Convert all files under current directory and its sub-directories into UTF-8 file naming method.")
		fmt.Println("./fsconv -um 	Convert all files under current directory and its sub-directories into UM File Naming Method representation.")
		fmt.Println("./fsconv -i {filepath_to_be_conv_to_UTF8}")
		fmt.Println("./fsconv -um {filepath_to_be_conv_to_UM-filenames")
	} else {
		//Given target directory
	}
}
