// Copyright 2015 Google Inc. All rights reserved.
//
// Licensed 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.

// soong_zip is a utility used during the build to create a zip archive by pulling the entries from
// various sources:
//  * explicitly specified files
//  * files whose paths are read from a file
//  * directories traversed recursively
// It can optionally change the recorded path of an entry.

package main

import (
	"flag"
	"fmt"
	"os"
	"runtime"
	"runtime/pprof"
	"runtime/trace"
	"strconv"
	"strings"

	"android/soong/response"
	"android/soong/zip"
)

type uniqueSet map[string]bool

func (u *uniqueSet) String() string {
	return `""`
}

func (u *uniqueSet) Set(s string) error {
	if _, found := (*u)[s]; found {
		return fmt.Errorf("File %q was specified twice as a file to not deflate", s)
	} else {
		(*u)[s] = true
	}

	return nil
}

type file struct{}

func (file) String() string { return `""` }

func (file) Set(s string) error {
	fileArgsBuilder.File(s)
	return nil
}

type listFiles struct{}

func (listFiles) String() string { return `""` }

func (listFiles) Set(s string) error {
	fileArgsBuilder.List(s)
	return nil
}

type rspFiles struct{}

func (rspFiles) String() string { return `""` }

func (rspFiles) Set(s string) error {
	fileArgsBuilder.RspFile(s)
	return nil
}

type dir struct{}

func (dir) String() string { return `""` }

func (dir) Set(s string) error {
	fileArgsBuilder.Dir(s)
	return nil
}

type relativeRoot struct{}

func (relativeRoot) String() string { return "" }

func (relativeRoot) Set(s string) error {
	fileArgsBuilder.SourcePrefixToStrip(s)
	return nil
}

type junkPaths struct{}

func (junkPaths) IsBoolFlag() bool { return true }
func (junkPaths) String() string   { return "" }

func (junkPaths) Set(s string) error {
	v, err := strconv.ParseBool(s)
	fileArgsBuilder.JunkPaths(v)
	return err
}

type rootPrefix struct{}

func (rootPrefix) String() string { return "" }

func (rootPrefix) Set(s string) error {
	fileArgsBuilder.PathPrefixInZip(s)
	return nil
}

var (
	fileArgsBuilder  = zip.NewFileArgsBuilder()
	nonDeflatedFiles = make(uniqueSet)
)

func main() {
	var expandedArgs []string
	for _, arg := range os.Args {
		if strings.HasPrefix(arg, "@") {
			f, err := os.Open(strings.TrimPrefix(arg, "@"))
			if err != nil {
				fmt.Fprintln(os.Stderr, err.Error())
				os.Exit(1)
			}

			respArgs, err := response.ReadRspFile(f)
			f.Close()
			if err != nil {
				fmt.Fprintln(os.Stderr, err.Error())
				os.Exit(1)
			}
			expandedArgs = append(expandedArgs, respArgs...)
		} else {
			expandedArgs = append(expandedArgs, arg)
		}
	}

	flags := flag.NewFlagSet("flags", flag.ExitOnError)
	flags.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: soong_zip -o zipfile [-m manifest] [-C dir] [-f|-l file] [-D dir]...\n")
		flags.PrintDefaults()
		os.Exit(2)
	}

	out := flags.String("o", "", "file to write zip file to")
	manifest := flags.String("m", "", "input jar manifest file name")
	directories := flags.Bool("d", false, "include directories in zip")
	compLevel := flags.Int("L", 5, "deflate compression level (0-9)")
	emulateJar := flags.Bool("jar", false, "modify the resultant .zip to emulate the output of 'jar'")
	writeIfChanged := flags.Bool("write_if_changed", false, "only update resultant .zip if it has changed")
	ignoreMissingFiles := flags.Bool("ignore_missing_files", false, "continue if a requested file does not exist")
	symlinks := flags.Bool("symlinks", true, "store symbolic links in zip instead of following them")
	srcJar := flags.Bool("srcjar", false, "move .java files to locations that match their package statement")

	parallelJobs := flags.Int("parallel", runtime.NumCPU(), "number of parallel threads to use")
	cpuProfile := flags.String("cpuprofile", "", "write cpu profile to file")
	traceFile := flags.String("trace", "", "write trace to file")

	flags.Var(&rootPrefix{}, "P", "path prefix within the zip at which to place files")
	flags.Var(&listFiles{}, "l", "file containing list of files to zip")
	flags.Var(&rspFiles{}, "r", "file containing list of files to zip with Ninja rsp file escaping")
	flags.Var(&dir{}, "D", "directory to include in zip")
	flags.Var(&file{}, "f", "file to include in zip")
	flags.Var(&nonDeflatedFiles, "s", "file path to be stored within the zip without compression")
	flags.Var(&relativeRoot{}, "C", "path to use as relative root of files in following -f, -l, or -D arguments")
	flags.Var(&junkPaths{}, "j", "junk paths, zip files without directory names")

	flags.Parse(expandedArgs[1:])

	if flags.NArg() > 0 {
		fmt.Fprintf(os.Stderr, "unexpected arguments %s\n", strings.Join(flags.Args(), " "))
		flags.Usage()
	}

	if *cpuProfile != "" {
		f, err := os.Create(*cpuProfile)
		if err != nil {
			fmt.Fprintln(os.Stderr, err.Error())
			os.Exit(1)
		}
		defer f.Close()
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	if *traceFile != "" {
		f, err := os.Create(*traceFile)
		if err != nil {
			fmt.Fprintln(os.Stderr, err.Error())
			os.Exit(1)
		}
		defer f.Close()
		err = trace.Start(f)
		if err != nil {
			fmt.Fprintln(os.Stderr, err.Error())
			os.Exit(1)
		}
		defer trace.Stop()
	}

	if fileArgsBuilder.Error() != nil {
		fmt.Fprintln(os.Stderr, fileArgsBuilder.Error())
		os.Exit(1)
	}

	err := zip.Zip(zip.ZipArgs{
		FileArgs:                 fileArgsBuilder.FileArgs(),
		OutputFilePath:           *out,
		EmulateJar:               *emulateJar,
		SrcJar:                   *srcJar,
		AddDirectoryEntriesToZip: *directories,
		CompressionLevel:         *compLevel,
		ManifestSourcePath:       *manifest,
		NumParallelJobs:          *parallelJobs,
		NonDeflatedFiles:         nonDeflatedFiles,
		WriteIfChanged:           *writeIfChanged,
		StoreSymlinks:            *symlinks,
		IgnoreMissingFiles:       *ignoreMissingFiles,
	})
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err.Error())
		os.Exit(1)
	}
}
