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

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"

	"mynewt.apache.org/newt/newt/downloader"
	"mynewt.apache.org/newt/newt/interfaces"
	"mynewt.apache.org/newt/util"
)

const REPO_NAME_LOCAL = "local"
const REPO_DEFAULT_PERMS = 0755

const REPO_FILE_NAME = "repository.yml"
const REPOS_DIR = "repos"

type Repo struct {
	name       string
	downloader downloader.Downloader
	localPath  string
	versreq    []interfaces.VersionReqInterface
	rdesc      *RepoDesc
}

type RepoDesc struct {
	name string
	vers map[*Version]string
}

func (rd *RepoDesc) MatchVersion(searchVers *Version) (string, *Version, bool) {
	for vers, curBranch := range rd.vers {
		if vers.CompareVersions(vers, searchVers) == 0 {
			return curBranch, vers, true
		}
	}
	return "", nil, false
}

func (rd *RepoDesc) Match(r *Repo) (string, *Version, bool) {
	for vers, branch := range rd.vers {
		if vers.SatisfiesVersion(r.VersionRequirements()) {
			log.Printf("[DEBUG] Found matching version %s for repo %s",
				vers.String(), r.Name())
			if vers.Stability() != VERSION_STABILITY_NONE {
				searchVers, err := LoadVersion(branch)
				if err != nil {
					return "", nil, false
				}

				var ok bool
				branch, vers, ok = rd.MatchVersion(searchVers)
				if !ok {
					return "", nil, false
				}
			}

			return branch, vers, true
		}
	}

	return "", nil, false
}

func (rd *RepoDesc) SatisfiesVersion(vers *Version, versReqs []interfaces.VersionReqInterface) bool {
	var err error
	versMatches := []interfaces.VersionReqInterface{}
	for _, versReq := range versReqs {
		versMatch := &VersionMatch{}
		versMatch.compareType = versReq.CompareType()

		if versReq.Version().Stability() != VERSION_STABILITY_NONE {
			// Look up this item in the RepoDescription, and get a version
			searchVers := versReq.Version().(*Version)
			branch, _, ok := rd.MatchVersion(searchVers)
			if !ok {
				return false
			}
			versMatch.Vers, err = LoadVersion(branch)
			if err != nil {
				return false
			}
		} else {
			versMatch.Vers = versReq.Version().(*Version)
		}

		versMatches = append(versMatches, versMatch)
	}

	return vers.SatisfiesVersion(versMatches)
}

func (rd *RepoDesc) Init(name string, versBranchMap map[string]string) error {
	rd.name = name
	rd.vers = map[*Version]string{}
	for versStr, branch := range versBranchMap {
		log.Printf("[DEBUG] Printing version %s for remote repo %s", versStr, name)
		vers, err := LoadVersion(versStr)
		if err != nil {
			return err
		}

		// store branch->version mapping
		rd.vers[vers] = branch
	}

	return nil
}

func (rd *RepoDesc) String() string {
	name := rd.name + "@"
	for k, v := range rd.vers {
		name += fmt.Sprintf("%s=%s", k.String(), v)
		name += "#"
	}

	return name
}

func NewRepoDesc(name string, versBranchMap map[string]string) (*RepoDesc, error) {
	rd := &RepoDesc{}

	if err := rd.Init(name, versBranchMap); err != nil {
		return nil, err
	}

	return rd, nil
}

func (r *Repo) GetRepoDesc() (*RepoDesc, error) {
	if r.rdesc == nil {
		return nil, util.NewNewtError(fmt.Sprintf(
			"Repository description for %s not yet initailized.  Must "+
				"download it first. ", r.Name()))
	} else {
		return r.rdesc, nil
	}
}

func (r *Repo) Name() string {
	return r.name
}

func (r *Repo) Path() string {
	return r.localPath
}

func (r *Repo) IsLocal() bool {
	return r.name == REPO_NAME_LOCAL
}

func (r *Repo) VersionRequirements() []interfaces.VersionReqInterface {
	return r.versreq
}

func (r *Repo) VersionRequirementsString() string {
	str := ""
	for _, vreq := range r.versreq {
		str += vreq.String()
	}

	return str
}

func (r *Repo) repoFilePath() string {
	return interfaces.GetProject().Path() + "/" + REPOS_DIR + "/" +
		".configs/" + r.name + "/"
}

func (r *Repo) Install(force bool) (*Version, error) {
	// Copy the git repo into /repos/, error'ing out if the repo already exists
	if util.NodeExist(r.Path()) {
		if force {
			if err := os.RemoveAll(r.Path()); err != nil {
				return nil, util.NewNewtError(err.Error())
			}
		} else {
			return nil, util.NewNewtError(fmt.Sprintf("Repository %s already "+
				"exists in local tree, cannot install.  Provide -f to override.", r.Path()))
		}
	}

	branchName, vers, found := r.rdesc.Match(r)
	if !found {
		return nil, util.NewNewtError(fmt.Sprintf("No repository matching description %s found",
			r.rdesc.String()))
	}

	dl := r.downloader

	// Download the git repo, returns the git repo, checked out to that branch
	tmpdir, err := dl.DownloadRepo(branchName)
	if err != nil {
		return nil, util.NewNewtError(fmt.Sprintf("Error download repository %s, : %s",
			r.Name(), err.Error()))
	}

	// Copy the Git repo into the the desired local path of the repo
	if err := util.CopyDir(tmpdir, r.Path()); err != nil {
		// Cleanup any directory that might have been created if we error out
		// here.
		os.RemoveAll(r.Path())
		return nil, err
	}

	return vers, nil
}

func (r *Repo) UpdateDesc() ([]*Repo, error) {
	var err error

	if err = r.DownloadDesc(); err != nil {
		return []*Repo{}, err
	}

	_, err = r.ReadDesc()
	if err != nil {
		return []*Repo{}, err
	}

	return []*Repo{}, nil
}

// Download the repository description.
func (r *Repo) DownloadDesc() error {
	dl := r.downloader

	util.StatusMessage(util.VERBOSITY_DEFAULT, fmt.Sprintf("Downloading "+
		"repository description for %s...", r.Name()))

	// Configuration path
	cpath := r.repoFilePath()
	if util.NodeNotExist(cpath) {
		if err := os.MkdirAll(cpath, REPO_DEFAULT_PERMS); err != nil {
			return util.NewNewtError(err.Error())
		}
	}

	dl.SetBranch("master")
	if err := dl.FetchFile("repository.yml",
		cpath+"/"+"repository.yml"); err != nil {
		util.StatusMessage(util.VERBOSITY_DEFAULT, " failed\n")
		return err
	}

	util.StatusMessage(util.VERBOSITY_DEFAULT, " success!\n")

	return nil
}

func (r *Repo) ReadDesc() (*RepoDesc, error) {
	if util.NodeNotExist(r.repoFilePath() + REPO_FILE_NAME) {
		return nil,
			util.NewNewtError("No configuration exists for repository " + r.name)
	}

	v, err := util.ReadConfig(r.repoFilePath(),
		strings.TrimSuffix(REPO_FILE_NAME, ".yml"))
	if err != nil {
		return nil, err
	}

	name := v.GetString("repo.name")
	versMap := v.GetStringMapString("repo.versions")

	rdesc, err := NewRepoDesc(name, versMap)
	if err != nil {
		return nil, err
	}
	r.rdesc = rdesc

	return rdesc, nil
}

func (r *Repo) Init(repoName string, rversreq string, d downloader.Downloader) error {
	var err error

	r.name = repoName
	r.downloader = d
	r.versreq, err = LoadVersionMatches(rversreq)
	if err != nil {
		return err
	}

	path := interfaces.GetProject().Path()

	if r.name == REPO_NAME_LOCAL {
		r.localPath = filepath.Clean(path)
	} else {
		r.localPath = filepath.Clean(path + "/" + REPOS_DIR + "/" + r.name)
	}

	return nil
}

func NewRepo(repoName string, rversreq string, d downloader.Downloader) (*Repo, error) {
	r := &Repo{}

	if err := r.Init(repoName, rversreq, d); err != nil {
		return nil, err
	}

	return r, nil
}

func NewLocalRepo() (*Repo, error) {
	r := &Repo{}

	if err := r.Init(REPO_NAME_LOCAL, "", nil); err != nil {
		return nil, err
	}

	return r, nil
}
