// Copyright © 2019 IBM Corporation and others.
//
// 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.

package cmd

import (
	"regexp"
	"strings"

	"github.com/pkg/errors"

	"github.com/spf13/cobra"
)

func newRepoAddCmd(config *RootCommandConfig) *cobra.Command {
	// initCmd represents the init command
	var addCmd = &cobra.Command{
		Use:   "add <repository> <url>",
		Short: "Add an Appsody repository.",
		Long:  `Add an Appsody repository to your list of configured Appsody repositories.`,
		Example: `  appsody repo add my-local-repo file:///absolute/path/to/my-local-repo.yaml
  Adds the "my-local-repo" repository, specified by the "file:///absolute/path/to/my-local-repo.yaml" file to your list of repositories.`,
		RunE: func(cmd *cobra.Command, args []string) error {
			if len(args) < 2 {
				return errors.New("You must specify a repository name and URL")
			}
			if len(args) > 2 {
				return errors.Errorf("Two arguments expected. Use 'appsody [command] --help' for more information about a command")
			}
			return repoAdd(args[0], args[1], config)
		},
	}
	return addCmd
}

func repoAdd(repoName, repoURL string, config *RootCommandConfig) error {

	if len(repoName) > 50 {
		return errors.Errorf("Invalid repository name. The <name> must be less than 50 characters")

	}
	match, _ := regexp.MatchString("^[a-zA-Z0-9\\-_\\.]{1,50}$", repoName)
	if !match {
		return errors.Errorf("Invalid repository name. The name can contain only letters (lowercase or uppercase), numbers, dashes '-', underscores '_', and periods '.'")

	}

	var repoFile RepositoryFile

	_, repoErr := repoFile.getRepos(config)
	if repoErr != nil {
		return repoErr
	}
	if repoFile.Has(repoName) {
		return errors.Errorf("A repository with the name '%s' already exists.", repoName)

	}
	if repoFile.HasURL(repoURL) {
		return errors.Errorf("A repository with the URL '%s' already exists.", repoURL)

	}
	index, err := downloadIndex(config.LoggingConfig, repoURL)
	if err != nil {
		return errors.Errorf("Could not download index. Does the APIVersion of your repository match what the Appsody CLI currently supports? (%v) Full error:  %v", supportedIndexAPIVersion, err)
	}
	if strings.Compare(index.APIVersion, supportedIndexAPIVersion) == 1 {
		config.Warning.log("The repository " + repoName + " contains an APIVersion in its .yaml file more recent than the current Appsody CLI supports(" + supportedIndexAPIVersion + "), it is strongly suggested that you update your Appsody CLI to the latest version.")
	}
	if index.APIVersion == "v1" {
		return errors.Errorf("The repository .yaml for " + repoName + " has an older APIVersion that the Appsody CLI no longer supports. Supported APIVersion: " + supportedIndexAPIVersion)
	}

	if config.Dryrun {
		config.Info.logf("Dry Run - Skipping appsody repo add repository Name: %s, URL: %s", repoName, repoURL)
	} else {
		var newEntry = RepositoryEntry{
			Name: repoName,
			URL:  repoURL,
		}

		repoFile.Add(&newEntry)
		err = repoFile.WriteFile(getRepoFileLocation(config))
		if err != nil {
			return errors.Errorf("Failed to write file to repository location: %v", err)
		}
	}
	return nil
}
