// 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"

	"go.fuchsia.dev/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
}
