/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strings"

	camelapiv1 "github.com/apache/camel-kamelets/crds/pkg/apis/camel/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/util/yaml"
)

func main() {
	if len(os.Args) != 3 {
		println("usage: generator kamelets-path doc-root")
		os.Exit(1)
	}

	projectBaseDir := os.Args[1]
	docBaseDir := os.Args[2]

	kamelets := listKamelets(projectBaseDir)

	links := make([]string, 0)
	for _, k := range kamelets {
		links = updateImageLink(k, links)
	}

	saveNav(links, docBaseDir)
}

func updateImageLink(k camelapiv1.Kamelet, links []string) []string {
	return append(links, fmt.Sprintf("* xref:%s.adoc[]", k.Name))
}

func saveNav(links []string, out string) {
	content := "// THIS FILE IS AUTOMATICALLY GENERATED: DO NOT EDIT\n"
	for _, l := range links {
		content += l + "\n"
	}
	content += "// THIS FILE IS AUTOMATICALLY GENERATED: DO NOT EDIT\n"
	dest := filepath.Join(out, "nav.adoc")
	if _, err := os.Stat(dest); err == nil {
		err = os.Remove(dest)
		handleGeneralError(fmt.Sprintf("cannot remove file %q", dest), err)
	}
	err := os.WriteFile(dest, []byte(content), 0666)
	handleGeneralError(fmt.Sprintf("cannot write file %q", dest), err)
	fmt.Printf("%q written\n", dest)
}

func listKamelets(dir string) []camelapiv1.Kamelet {
	scheme := runtime.NewScheme()
	err := camelapiv1.AddToScheme(scheme)
	handleGeneralError("cannot to add camel APIs to scheme", err)

	kamelets := make([]camelapiv1.Kamelet, 0)
	files, err := os.ReadDir(dir)
	filesSorted := make([]string, 0)
	handleGeneralError(fmt.Sprintf("cannot list dir %q", dir), err)
	for _, fd := range files {
		if !fd.IsDir() && strings.HasSuffix(fd.Name(), ".kamelet.yaml") {
			fullName := filepath.Join(dir, fd.Name())
			filesSorted = append(filesSorted, fullName)
		}
	}
	sort.Strings(filesSorted)
	for _, fileName := range filesSorted {
		yamlContent, err := os.ReadFile(fileName)
		handleGeneralError(fmt.Sprintf("cannot read file %q", fileName), err)
		jsonContent, err := yaml.ToJSON(yamlContent)
		handleGeneralError(fmt.Sprintf("cannot convert yaml file %q into json", fileName), err)
		var kamelet *camelapiv1.Kamelet
		err = yaml.Unmarshal(jsonContent, &kamelet)
		handleGeneralError(fmt.Sprintf("cannot unmarshal file %q into Kamelet", fileName), err)
		kamelets = append(kamelets, *kamelet)
	}
	return kamelets
}

func handleGeneralError(desc string, err error) {
	if err != nil {
		fmt.Printf("%s: %+v\n", desc, err)
		os.Exit(2)
	}
}
