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

import (
	"fmt"

	"github.com/spf13/cobra"
)

func newCmdInspect(rootCmdOptions *RootCmdOptions) (*cobra.Command, *inspectCmdOptions) {
	options := inspectCmdOptions{
		RootCmdOptions: rootCmdOptions,
	}

	cmd := cobra.Command{
		Use:   "inspect [files to inspect]",
		Short: "Generate dependencies list given integration files.",
		Long: `Output dependencies for a list of integration files. By default this command returns the
top level dependencies only. When --all-dependencies is enabled, the transitive dependencies
will be generated by calling Maven and then printed in the selected output format.`,
		PreRunE: decode(&options),
		RunE: func(_ *cobra.Command, args []string) error {
			if err := options.validate(args); err != nil {
				return err
			}
			if err := options.init(); err != nil {
				return err
			}
			if err := options.run(args); err != nil {
				fmt.Println(err.Error())
			}
			if err := options.deinit(); err != nil {
				return err
			}

			return nil
		},
		Annotations: map[string]string{
			offlineCommandLabel: "true",
		},
	}

	cmd.Flags().Bool("all-dependencies", false, "Compute transitive dependencies and move them to directory pointed to by the --dependencies-directory flag.")
	cmd.Flags().StringArrayP("dependency", "d", nil, additionalDependencyUsageMessage)
	cmd.Flags().StringP("output", "o", "", "Output format. One of: json|yaml")

	return &cmd, &options
}

type inspectCmdOptions struct {
	*RootCmdOptions
	AllDependencies        bool     `mapstructure:"all-dependencies"`
	OutputFormat           string   `mapstructure:"output"`
	AdditionalDependencies []string `mapstructure:"dependencies"`
}

func (command *inspectCmdOptions) validate(args []string) error {
	// Validate integration files.
	err := validateIntegrationFiles(args)
	if err != nil {
		return err
	}

	// Validate additional dependencies specified by the user.
	err = validateAdditionalDependencies(command.AdditionalDependencies)
	if err != nil {
		return err
	}

	return nil
}

func (command *inspectCmdOptions) init() error {
	return createMavenWorkingDirectory()
}

func (command *inspectCmdOptions) run(args []string) error {
	// Fetch dependencies.
	dependencies, err := getDependencies(args, command.AdditionalDependencies, command.AllDependencies)
	if err != nil {
		return err
	}

	// Print dependencies.
	err = outputDependencies(dependencies, command.OutputFormat)
	if err != nil {
		return err
	}

	return nil
}

func (command *inspectCmdOptions) deinit() error {
	return deleteMavenWorkingDirectory()
}
