package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/buildpacks/pack/cmd"
	"github.com/buildpacks/pack/pkg/logging"
	"github.com/spf13/cobra/doc"
)

var ansiEscape = regexp.MustCompile(`\x1b\[[0-9;]*m`)

const (
	cliDir     = "/docs/for-platform-operators/how-to/integrate-ci/pack/cli/"
	outputPath = "../content" + cliDir
	indexFile  = `_index.md`

	gendocFrontmatterTemplate = `+++
title="%s"
no_edit="true"
aliases=[ "%s" ]
+++
<!--more-->
`
)

var filePrepender = func(filename string) string {
	name := filepath.Base(filename)
	name = strings.Replace(name, ".md", "", -1)
	presentationName := strings.Replace(name, "_", " ", -1)
	alias := fmt.Sprintf("/docs/tools/pack/cli/%s", name)
	return fmt.Sprintf(gendocFrontmatterTemplate, presentationName, alias)
}

var linkHandler = func(name string) string {
	base := strings.TrimSuffix(name, path.Ext(name))
	return cliDir + strings.ToLower(base) + "/"
}

func main() {
	packCmd, err := cmd.NewPackCommand(newLogger())
	if err != nil {
		log.Fatal(err)
	}
	packCmd.DisableAutoGenTag = true

	if _, err := os.Stat(outputPath); os.IsNotExist(err) {
		if err := os.MkdirAll(outputPath, 0777); err != nil {
			log.Fatal(err)
		}
	}

	if _, err := os.Stat(filepath.Join(outputPath, indexFile)); os.IsNotExist(err) {
		if err := os.WriteFile(filepath.Join(outputPath, indexFile), []byte(filePrepender("Pack CLI")), os.ModePerm); err != nil {
			log.Fatal(err)
		}
	}

	err = doc.GenMarkdownTreeCustom(packCmd, outputPath, filePrepender, linkHandler)
	if err != nil {
		log.Fatal(err)
	}

	if err := stripANSIFromDir(outputPath); err != nil {
		log.Fatal(err)
	}
}

func stripANSIFromDir(dir string) error {
	return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil || info.IsDir() || filepath.Ext(path) != ".md" {
			return err
		}
		data, err := os.ReadFile(path)
		if err != nil {
			return err
		}
		cleaned := ansiEscape.ReplaceAll(data, nil)
		if len(cleaned) == len(data) {
			return nil
		}
		return os.WriteFile(path, cleaned, info.Mode())
	})
}

type packLogger struct {
	logging.Logger
}

func (l packLogger) WantTime(f bool)    {}
func (l packLogger) WantQuiet(f bool)   {}
func (l packLogger) WantVerbose(f bool) {}

func newLogger() packLogger {
	log := logging.NewSimpleLogger(ioutil.Discard)
	return packLogger{
		log,
	}
}
