// Package cache provides an interface for interfacing with the Glide local cache
//
// Glide has a local cache of metadata and repositories similar to the GOPATH.
// To store the cache Glide creates a .glide directory with a cache subdirectory.
// This is usually in the users home directory unless there is no accessible
// home directory in which case the .glide directory is in the root of the
// repository.
//
// To get the cache location use the `cache.Location()` function. This will
// return the proper base location in your environment.
//
// Within the cache directory there are two subdirectories. They are the src
// and info directories. The src directory contains version control checkouts
// of the packages. The info direcory contains metadata. The metadata maps to
// the RepoInfo struct. Both stores are happed to keys.
//
// Using the `cache.Key()` function you can get a key for a repo. Pass in a
// location such as `https://github.com/foo/bar` or `git@example.com:foo.git`
// and a key will be returned that can be used for caching operations.
//
// Note, the caching is based on repo rather than package. This is important
// for a couple reasons.
//
// 1. Forks or package replacements are supported in Glide. Where a different
//    repo maps to a package.
// 2. Permissions enable different access. For example `https://example.com/foo.git`
//    and `git@example.com:foo.git` may have access to different branches or tags.
package cache

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/url"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
	"time"

	"github.com/Masterminds/glide/msg"
	gpath "github.com/Masterminds/glide/path"
)

// Enabled sets if the cache is globally enabled. Defaults to true.
var Enabled = true

// ErrCacheDisabled is returned with the cache is disabled.
var ErrCacheDisabled = errors.New("Cache disabled")

var isSetup bool

var setupMutex sync.Mutex

// Setup creates the cache location.
func Setup() {
	setupMutex.Lock()
	defer setupMutex.Unlock()

	if isSetup {
		return
	}
	msg.Debug("Setting up the cache directory")
	pths := []string{
		"cache",
		filepath.Join("cache", "src"),
		filepath.Join("cache", "info"),
	}

	for _, l := range pths {
		err := os.MkdirAll(filepath.Join(gpath.Home(), l), 0755)
		if err != nil {
			msg.Die("Cache directory unavailable: %s", err)
		}
	}

	isSetup = true
}

// SetupReset resets if setup has been completed. The next time setup is run
// it will attempt a full setup.
func SetupReset() {
	isSetup = false
}

// Location returns the location of the cache.
func Location() string {
	p := filepath.Join(gpath.Home(), "cache")
	Setup()

	return p
}

// scpSyntaxRe matches the SCP-like addresses used to access repos over SSH.
var scpSyntaxRe = regexp.MustCompile(`^([a-zA-Z0-9_]+)@([a-zA-Z0-9._-]+):(.*)$`)

// Key generates a cache key based on a url or scp string. The key is file
// system safe.
func Key(repo string) (string, error) {

	var u *url.URL
	var err error
	var strip bool
	if m := scpSyntaxRe.FindStringSubmatch(repo); m != nil {
		// Match SCP-like syntax and convert it to a URL.
		// Eg, "git@github.com:user/repo" becomes
		// "ssh://git@github.com/user/repo".
		u = &url.URL{
			Scheme: "ssh",
			User:   url.User(m[1]),
			Host:   m[2],
			Path:   "/" + m[3],
		}
		strip = true
	} else {
		u, err = url.Parse(repo)
		if err != nil {
			return "", err
		}
	}

	if strip {
		u.Scheme = ""
	}

	var key string
	if u.Scheme != "" {
		key = u.Scheme + "-"
	}
	if u.User != nil && u.User.Username() != "" {
		key = key + u.User.Username() + "-"
	}
	key = key + u.Host
	if u.Path != "" {
		key = key + strings.Replace(u.Path, "/", "-", -1)
	}

	key = strings.Replace(key, ":", "-", -1)

	return key, nil
}

// RepoInfo holds information about a repo.
type RepoInfo struct {
	DefaultBranch string `json:"default-branch"`
	LastUpdate    string `json:"last-update"`
}

// SaveRepoData stores data about a repo in the Glide cache
func SaveRepoData(key string, data RepoInfo) error {
	if !Enabled {
		return ErrCacheDisabled
	}
	location := Location()
	data.LastUpdate = time.Now().String()
	d, err := json.Marshal(data)
	if err != nil {
		return err
	}

	pp := filepath.Join(location, "info")
	err = os.MkdirAll(pp, 0755)
	if err != nil {
		return err
	}

	p := filepath.Join(pp, key+".json")
	f, err := os.Create(p)
	if err != nil {
		return err
	}
	defer f.Close()

	_, err = f.Write(d)
	return err
}

// RepoData retrieves cached information about a repo.
func RepoData(key string) (*RepoInfo, error) {
	if !Enabled {
		return &RepoInfo{}, ErrCacheDisabled
	}
	location := Location()
	c := &RepoInfo{}
	p := filepath.Join(location, "info", key+".json")
	f, err := ioutil.ReadFile(p)
	if err != nil {
		return &RepoInfo{}, err
	}
	err = json.Unmarshal(f, c)
	if err != nil {
		return &RepoInfo{}, err
	}
	return c, nil
}

var lockSync sync.Mutex

var lockData = make(map[string]*sync.Mutex)

// Lock locks a particular key name
func Lock(name string) {
	lockSync.Lock()
	m, ok := lockData[name]
	if !ok {
		m = &sync.Mutex{}
		lockData[name] = m
	}
	lockSync.Unlock()
	msg.Debug("Locking %s", name)
	m.Lock()
}

// Unlock unlocks a particular key name
func Unlock(name string) {
	msg.Debug("Unlocking %s", name)
	lockSync.Lock()
	if m, ok := lockData[name]; ok {
		m.Unlock()
	}

	lockSync.Unlock()
}
