package servicegen

import (
	"os"
	"path/filepath"
	"text/template"
)

/* 生成整个项目结构
- hasaki-service-app
	- hasaki-app
		- api.go
		- api_pre.go
		- api_test.go
		- api_task.go
		- db_model.go
		- handler.go
		- initialize.go
	- hasaki-app-options
		- options.go
	- hasaki-app-external
		- external.go
*/
func Gen(name string) error {
	err := genService(name)
	if err != nil {
		return err
	}
	err = genApp(name)
	if err != nil {
		return err
	}
	err = genOptions(name)
	if err != nil {
		return err
	}
	err = genExternal(name)
	if err != nil {
		return err
	}
	return nil
}

func genService(appName string) error {
	rootDir, err := getRootDir(appName)
	if err != nil {
		return err
	}

	err = os.Mkdir(rootDir, os.ModeDir)
	if err != nil {
		return err
	}

	err = parseTpl(mainTpl, filepath.Join(rootDir, "main.go"), appName)
	if err != nil {
		return err
	}
	err = parseTpl(configJsonTpl, filepath.Join(rootDir, "config.json"), appName)
	if err != nil {
		return err
	}

	return nil
}

func genApp(appName string) error {
	appDir, err := getAppDir(appName)
	if err != nil {
		return err
	}

	err = os.Mkdir(appDir, os.ModeDir)
	if err != nil {
		return err
	}

	// api.go
	err = parseTpl(apiTpl, filepath.Join(appDir, "api.go"), appName)
	if err != nil {
		return err
	}

	// api_pre.go
	err = parseTpl(apiPreTpl, filepath.Join(appDir, "api_pre.go"), appName)
	if err != nil {
		return err
	}

	// api_task.go
	err = parseTpl(apiTaskTpl, filepath.Join(appDir, "api_task.go"), appName)
	if err != nil {
		return err
	}

	// api_test.go
	err = parseTpl(apiTestTpl, filepath.Join(appDir, "api_test.go"), appName)
	if err != nil {
		return err
	}

	err = parseTpl(dbModelTpl, filepath.Join(appDir, "db_model.go"), appName)
	if err != nil {
		return err
	}

	err = parseTpl(initializeTpl, filepath.Join(appDir, "initialize.go"), appName)
	if err != nil {
		return err
	}

	err = parseTpl(adminInitializeTpl, filepath.Join(appDir, "initialize_amdin.go"), appName)
	if err != nil {
		return err
	}

	return nil
}

func genOptions(appName string) error {
	optionsDir, err := getOptionsDir(appName)
	if err != nil {
		return err
	}
	err = os.Mkdir(optionsDir, os.ModeDir)
	if err != nil {
		return err
	}
	err = parseTpl(optionsTpl, filepath.Join(optionsDir, "options.go"), appName)
	if err != nil {
		return err
	}
	return nil
}

func genExternal(appName string) error {
	externalDir, err := getExternal(appName)
	if err != nil {
		return err
	}
	err = os.Mkdir(externalDir, os.ModeDir)
	if err != nil {
		return err
	}
	err = parseTpl(externalTpl, filepath.Join(externalDir, "extenral.go"), appName)
	if err != nil {
		return err
	}
	return nil
}

func getRootDir(appName string) (string, error) {
	rootDir := "hasaki-service-" + appName
	pwd, err := os.Getwd()
	if err != nil {
		return "", err
	}
	path := filepath.Join(pwd, rootDir)
	return path, nil
}

func getAppDir(appName string) (string, error) {
	appDir := "hasaki_" + appName
	rootDir, err := getRootDir(appName)
	if err != nil {
		return "", err
	}
	path := filepath.Join(rootDir, appDir)
	return path, nil
}

func getOptionsDir(appName string) (string, error) {
	optionsDir := "hasaki_" + appName + "_options"
	rootDir, err := getRootDir(appName)
	if err != nil {
		return "", err
	}
	path := filepath.Join(rootDir, optionsDir)
	return path, nil
}

func getExternal(appName string) (string, error) {
	externalDir := "hasaki_" + appName + "_external"
	rootDir, err := getRootDir(appName)
	if err != nil {
		return "", err
	}
	path := filepath.Join(rootDir, externalDir)
	return path, nil
}

func parseTpl(tmpl *template.Template, file string, appName string) error {
	f, err := os.Create(file)
	if err != nil {
		return err
	}
	err = tmpl.Execute(f, map[string]interface{}{"app_name": appName})
	if err != nil {
		return err
	}
	return nil
}