// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package jiri

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"syscall"

	"fuchsia.googlesource.com/jiri/osutil"
	"fuchsia.googlesource.com/jiri/version"
)

const (
	JiriRepository    = "https://fuchsia.googlesource.com/jiri"
	JiriStorageBucket = "https://storage.googleapis.com/fuchsia-build/jiri"
)

var (
	updateTestVersionErr  = fmt.Errorf("jiri has test version")
	updateVersionErr      = fmt.Errorf("jiri is already at latest version")
	updateNotAvailableErr = fmt.Errorf("latest version of jiri not available")
)

// Update checks whether a new version of Jiri is available and if so,
// it will download it and replace the current version with the new one.
func Update(force bool) error {
	if !force && version.GitCommit == "" {
		return updateTestVersionErr
	}
	commit, err := getCurrentCommit(JiriRepository)
	if err != nil {
		return err
	}
	if force || commit != version.GitCommit {
		// Check if the prebuilt for new version exsits.
		has, err := hasPrebuilt(JiriStorageBucket, commit)
		if err != nil {
			return fmt.Errorf("cannot check if prebuilt is available, %s", err)
		}
		if !has {
			return updateNotAvailableErr
		}

		// New version is available, download and update to it.
		b, err := downloadBinary(JiriStorageBucket, commit)
		if err != nil {
			return fmt.Errorf("cannot download latest jiri binary, %s", err)
		}
		path, err := osutil.Executable()
		if err != nil {
			return fmt.Errorf("cannot get executable path, %s", err)
		}
		return updateExecutable(path, b)
	}
	return updateVersionErr
}

func UpdateAndExecute(force bool) error {
	// Capture executable path before it is replaced in Update func
	path, err := osutil.Executable()
	if err != nil {
		return fmt.Errorf("cannot get executable path, %s", err)
	}
	if err := Update(force); err != nil {
		if err != updateNotAvailableErr && err != updateVersionErr &&
			err != updateTestVersionErr {
			return err
		} else {
			return nil
		}
	}

	args := []string{}
	for _, a := range os.Args {
		if !strings.HasPrefix(a, "-force-autoupdate") {
			args = append(args, a)
		}
	}

	// Run the update version.
	if err = syscall.Exec(path, args, os.Environ()); err != nil {
		return fmt.Errorf("cannot execute %s: %s", path, err)
	}
	return nil
}

func getCurrentCommit(repository string) (string, error) {
	u, err := url.Parse(repository)
	if err != nil {
		return "", err
	}
	if u.Scheme != "http" && u.Scheme != "https" {
		return "", fmt.Errorf("remote host scheme is not http(s): %s", repository)
	}
	u.Path = path.Join(u.Path, "+refs/heads/master")
	q := u.Query()
	q.Set("format", "json")
	u.RawQuery = q.Encode()

	// Use Gitiles to find out the latest revision.
	req, err := http.NewRequest("GET", u.String(), nil)
	if err != nil {
		return "", err
	}
	req.Header.Add("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return "", err
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		return "", fmt.Errorf("HTTP request failed: %v", http.StatusText(res.StatusCode))
	}

	r := bufio.NewReader(res.Body)

	// The first line of the input is the XSSI guard ")]}'".
	if _, err := r.ReadSlice('\n'); err != nil {
		return "", err
	}

	var result map[string]struct {
		Value string `json:"value"`
	}
	if err := json.NewDecoder(r).Decode(&result); err != nil {
		return "", err
	}
	if v, ok := result["refs/heads/master"]; ok {
		return v.Value, nil
	} else {
		return "", fmt.Errorf("cannot find current commit")
	}
}

func hasPrebuilt(bucket, version string) (bool, error) {
	url := fmt.Sprintf("%s/%s-%s/%s", bucket, runtime.GOOS, runtime.GOARCH, version)
	res, err := http.Head(url)
	if err != nil {
		return false, err
	}
	if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusNotFound {
		return false, fmt.Errorf("HTTP request failed: %v", http.StatusText(res.StatusCode))
	}
	return res.StatusCode == http.StatusOK, nil
}

func downloadBinary(bucket, version string) ([]byte, error) {
	url := fmt.Sprintf("%s/%s-%s/%s", bucket, runtime.GOOS, runtime.GOARCH, version)
	res, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	if res.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("HTTP request failed: %v", http.StatusText(res.StatusCode))
	}
	defer res.Body.Close()

	bytes, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}

	return bytes, nil
}

func updateExecutable(path string, b []byte) error {
	fi, err := os.Stat(path)
	if err != nil {
		return err
	}

	dir := filepath.Dir(path)

	// Write the new version to a file.
	newfile, err := ioutil.TempFile(dir, "jiri")
	if err != nil {
		return err
	}

	if _, err := newfile.Write(b); err != nil {
		return err
	}

	if err := newfile.Chmod(fi.Mode()); err != nil {
		return err
	}

	if err := newfile.Close(); err != nil {
		return err
	}

	// Backup the existing version.
	oldfile, err := ioutil.TempFile(dir, "jiri")
	if err != nil {
		return err
	}
	defer os.Remove(oldfile.Name())

	if err := oldfile.Close(); err != nil {
		return err
	}

	err = osutil.Rename(path, oldfile.Name())
	if err != nil {
		return err
	}

	// Replace the existing version.
	err = osutil.Rename(newfile.Name(), path)
	if err != nil {
		// Try to rollback the change in case of error.
		rerr := osutil.Rename(oldfile.Name(), path)
		if rerr != nil {
			return rerr
		}
		return err
	}

	return nil
}
