/*
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 (
	"testing"

	"github.com/apache/camel-k/pkg/util/test"
	"github.com/spf13/cobra"
)

func addTestLocalRunCmd(rootCmdOptions *RootCmdOptions, rootCmd *cobra.Command) *localRunCmdOptions {
	//add a testing version of run Command
	localCmd := newCmdLocal(rootCmdOptions)
	localRunCmd, localRunCmdOptions := newCmdLocalRun(rootCmdOptions)
	localRunCmd.RunE = func(c *cobra.Command, args []string) error {
		return nil
	}
	localRunCmd.Args = test.ArbitraryArgs
	localCmd.AddCommand(localRunCmd)
	rootCmd.AddCommand(localCmd)
	return localRunCmdOptions
}

func TestLocalRunPropertyFileFlag(t *testing.T) {
	options, rootCmd := kamelTestPreAddCommandInit()

	localRunCmdOptions := addTestLocalRunCmd(options, rootCmd)

	kamelTestPostAddCommandInit(t, rootCmd)

	_, err := test.ExecuteCommand(rootCmd, "local", "run", "route.java", "--property-file", "file1.properties", "--property-file", "file2.properties")
	if err != nil {
		t.Fatalf("Unexpected error: %v", err)
	}

	if len(localRunCmdOptions.PropertyFiles) != 2 {
		t.Fatalf("Property files expected to contain: \n %v elements\nGot:\n %v elements\n", 2, len(localRunCmdOptions.PropertyFiles))
	}
	if localRunCmdOptions.PropertyFiles[0] != "file1.properties" || localRunCmdOptions.PropertyFiles[1] != "file2.properties" {
		t.Fatalf("Property files expected to be: \n %v\nGot:\n %v\n", "[file1.properties, file2.properties]", localRunCmdOptions.PropertyFiles)
	}
}

func TestLocalRunAdditionalDependenciesFlag(t *testing.T) {
	options, rootCmd := kamelTestPreAddCommandInit()

	localRunCmdOptions := addTestLocalRunCmd(options, rootCmd)

	kamelTestPostAddCommandInit(t, rootCmd)

	_, err := test.ExecuteCommand(rootCmd, "local", "run", "route.java", "-d", "mvn:camel-component-1", "-d", "mvn:camel-component-2")
	if err != nil {
		t.Fatalf("Unexpected error: %v", err)
	}

	if len(localRunCmdOptions.AdditionalDependencies) != 2 {
		t.Fatalf("Additional dependencies expected to contain: \n %v elements\nGot:\n %v elements\n", 2, len(localRunCmdOptions.AdditionalDependencies))
	}
	if localRunCmdOptions.AdditionalDependencies[0] != "mvn:camel-component-1" || localRunCmdOptions.AdditionalDependencies[1] != "mvn:camel-component-2" {
		t.Fatalf("Additional dependencies expected to be: \n %v\nGot:\n %v\n", "[mvn:camel-component-1, mvn:camel-component-2]", localRunCmdOptions.AdditionalDependencies)
	}
}
