// Copyright 2016 The Vanadium 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 gerrit

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"

	"fuchsia.googlesource.com/jiri/collect"
)

// The functions in this file are provided to support writing a presubmit
// system that queries Gerrit for new changes and does <something> with them.

// ReadLog returns a map of CLs indexed by their refs, read from the given log file.
func ReadLog(logFilePath string) (CLRefMap, error) {
	results := CLRefMap{}
	bytes, err := ioutil.ReadFile(logFilePath)
	if err != nil {
		// File not existing is OK: just return an empty map of CLs.
		if os.IsNotExist(err) {
			return results, nil
		}
		return nil, fmt.Errorf("ReadFile(%q) failed: %v", logFilePath, err)
	}

	if err := json.Unmarshal(bytes, &results); err != nil {
		return nil, fmt.Errorf("Unmarshal failed reading file %q: %v", logFilePath, err)
	}
	return results, nil
}

// WriteLog writes the given list of CLs to a log file, as a json-encoded
// map of ref strings => CLs.
func WriteLog(logFilePath string, cls CLList) (e error) {
	// Index CLs with their refs.
	results := CLRefMap{}
	for _, cl := range cls {
		results[cl.Reference()] = cl
	}

	fd, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
	if err != nil {
		return fmt.Errorf("OpenFile(%q) failed: %v", logFilePath, err)
	}
	defer collect.Error(func() error { return fd.Close() }, &e)

	bytes, err := json.MarshalIndent(results, "", "  ")
	if err != nil {
		return fmt.Errorf("MarshalIndent(%v) failed: %v", results, err)
	}

	if err := ioutil.WriteFile(logFilePath, bytes, os.FileMode(0644)); err != nil {
		return fmt.Errorf("WriteFile(%q) failed: %v", logFilePath, err)
	}
	return nil
}

// NewOpenCLs returns a slice of CLLists that are "newer" relative to the
// previous query. A CLList is newer if one of the following condition holds:
// - If a CLList has only one cl, then it is newer if:
//   * Its ref string cannot be found among the CLs from the previous query.
//
//   For example: from the previous query, we got cl 1000/1 (cl number 1000 and
//   patchset 1). Then CLLists [1000/2] and [2000/1] are both newer.
//
// - If a CLList has multiple CLs, then it is newer if:
//   * It forms a "consistent" (its CLs have the same topic) and "complete"
//     (it contains all the parts) multi-part CL set.
//   * At least one of their ref strings cannot be found in the CLs from the
//     previous query.
//
//   For example: from the previous query, we got cl 3001/1 which is the first
//   part of a multi part cl set with topic "T1". Suppose the current query
//   returns cl 3002/1 which is the second part of the same set. In this case,
//   a CLList [3001/1 3002/1] will be returned. Then suppose in the next query,
//   we got cl 3002/2 which is newer then 3002/1. In this case, a CLList
//   [3001/1 3002/2] will be returned.
func NewOpenCLs(prevCLsMap CLRefMap, curCLs CLList) ([]CLList, []error) {
	retNewCLs := []CLList{}
	topicsInNewCLs := map[string]bool{}
	multiPartCLs := CLList{}
	for _, curCL := range curCLs {
		// Ref could be empty in cases where a patchset is causing conflicts.
		if curCL.Reference() == "" {
			continue
		}
		if _, ok := prevCLsMap[curCL.Reference()]; !ok { // This individual cl is newer.
			if curCL.MultiPart == nil {
				// This cl is not a multi part cl; add it to the return slice.
				retNewCLs = append(retNewCLs, CLList{curCL})
			} else {
				// This cl is a multi part cl; record its topic and process it later.
				topicsInNewCLs[curCL.MultiPart.Topic] = true
			}
		}
		// Record all multi part CLs.
		if curCL.MultiPart != nil {
			multiPartCLs = append(multiPartCLs, curCL)
		}
	}

	// Find complete multi part CL sets.
	setMap := map[string]*MultiPartCLSet{}
	retErrors := []error{}
	for _, curCL := range multiPartCLs {
		multiPartInfo := curCL.MultiPart

		// Skip topics that contain no new CLs.
		topic := multiPartInfo.Topic
		if !topicsInNewCLs[topic] {
			continue
		}

		// Golang equivalent of defaultdict...
		if _, ok := setMap[topic]; !ok {
			setMap[topic] = NewMultiPartCLSet()
		}

		curSet := setMap[topic]
		if err := curSet.AddCL(curCL); err != nil {
			// Errors adding multi part CLs aren't fatal since we want to keep processing
			// the rest of the CLs.  Return a list to the caller for probably just logging.
			retErrors = append(retErrors, NewChangeError(curCL, err))
		}
	}
	for _, set := range setMap {
		if set.Complete() {
			retNewCLs = append(retNewCLs, set.CLs())
		}
	}

	return retNewCLs, retErrors
}
