/*
 * 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

//
// The bundler turns files into resources contained in go code.
//
// This is useful for serving HTML and Javascript files from a self-contained binary.
//

import (
	"bufio"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

const APACHE_HEADER = `/*
 * 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.
 */
`

const GENERATED_CODE_COMMENT = "// THIS IS GENERATED CODE.  DO NOT EDIT."

var SEP string = string(os.PathSeparator)

// Return true if a file contains a given string.
func fileContainsString(path, line string) (bool, error) {
	file, err := os.Open(path)
	if err != nil {
		return false, err
	}
	defer file.Close()
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), line) {
			return true, nil
		}
	}
	if err := scanner.Err(); err != nil {
		return false, err
	}
	return false, nil
}

// Converts a source file path to a destination file path
func sfileToDfile(sfile string) string {
	return strings.Replace(sfile, SEP, "__", -1) + ".go"
}

// Delete generated files that are in dfiles but not sfiles.
// sfiles and dfiles must be sorted by file name.
func deleteUnusedDst(sfiles []string, dst string, dfiles []os.FileInfo) error {
	s := 0
	for d := range dfiles {
		fullDst := dst + SEP + dfiles[d].Name()
		generated, err := fileContainsString(fullDst, GENERATED_CODE_COMMENT)
		if err != nil {
			return err
		}
		if !generated {
			// Skip this destination file, since it is not generated.
			continue
		}
		found := false
		for {
			if s >= len(sfiles) {
				break
			}
			tgt := sfileToDfile(sfiles[s])
			if tgt == dfiles[d].Name() {
				found = true
				break
			}
			if tgt > dfiles[d].Name() {
				break
			}
			s++
		}
		if !found {
			log.Printf("Removing %s\n", fullDst)
			err := os.Remove(fullDst)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func createBundleFile(pkg, src, sfile, dst string) error {
	// Open destination file and write header.
	tgt := sfileToDfile(sfile)
	fullDst := dst + SEP + tgt
	out, err := os.Create(fullDst)
	if err != nil {
		return err
	}
	defer out.Close()
	_, err = out.WriteString(APACHE_HEADER)
	if err != nil {
		return err
	}
	_, err = out.WriteString("\n" + GENERATED_CODE_COMMENT + "\n")
	if err != nil {
		return err
	}
	_, err = out.WriteString(fmt.Sprintf("\npackage %s\n", pkg))
	if err != nil {
		return err
	}
	_, err = out.WriteString(fmt.Sprintf("var _ = addResource(\"%s\", `\n", tgt[:len(tgt)-3]))
	if err != nil {
		return err
	}

	// Open source file and create scanner.
	fullSrc := src + SEP + sfile
	in, err := os.Open(fullSrc)
	if err != nil {
		return err
	}
	defer in.Close()
	reader := bufio.NewReader(in)
	scanner := bufio.NewScanner(reader)
	for scanner.Scan() {
		str := strings.Replace(scanner.Text(), "`", "` + \"`\" + `", -1) + "\n"
		// Avoid "Unicode (UTF-8) BOM in middle of file" error.
		str = strings.Replace(str, "\uFEFF", "` + \"\\uFEFF\" + `", -1)
		_, err := out.WriteString(str)
		if err != nil {
			return err
		}
	}
	_, err = out.WriteString("`)\n")
	if err != nil {
		return err
	}
	err = out.Close()
	if err != nil {
		return err
	}
	return nil
}

var src = flag.String("src", "", "Source path for bundled resources.")
var dst = flag.String("dst", "", "Destination path for bundled resources.")
var pkg = flag.String("pkg", "resource", "Package name to use for bundled resources")

func main() {
	flag.Parse()
	if *src == "" {
		log.Fatal("You must supply a src directory to bundle.")
	}
	if *dst == "" {
		log.Fatal("You must supply a dst directory for output.")
	}
	sfiles := make([]string, 0, 32)
	absSrc, err := filepath.Abs(filepath.Clean(*src))
	if err != nil {
		log.Fatalf("Error getting absolute path for %s: %s\n", *src, err.Error())
	}
	err = filepath.Walk(absSrc, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() {
			return nil
		}
		var suffix string
		suffix, err = filepath.Rel(absSrc, path)
		if err != nil {
			return err
		}
		sfiles = append(sfiles, suffix)
		return nil
	})
	if err != nil {
		log.Fatalf("Error listing files in src directory %s: %s\n", absSrc, err.Error())
	}
	var dfiles []os.FileInfo
	dfiles, err = ioutil.ReadDir(*dst)
	if err != nil {
		log.Fatalf("Error listing files in output directory %s: %s\n", *dst, err.Error())
	}
	deleteUnusedDst(sfiles, *dst, dfiles)
	for s := range sfiles {
		err = createBundleFile(*pkg, absSrc, sfiles[s], *dst)
		if err != nil {
			log.Fatalf("Error creating bundle file for %s in %s: %s\n",
				sfiles[s], *dst, err.Error())
		}
		log.Printf("Bundled %s as %s\n", absSrc, *dst+SEP+sfileToDfile(sfiles[s]))
	}
}
