// Copyright 2021 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 apidiff

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

	"go.fuchsia.dev/fuchsia/tools/fidl/lib/summarize"
	yaml "gopkg.in/yaml.v2"
)

// ReportItem is a single line item of the API diff report.
type ReportItem struct {
	// Name is the fully qualified name that this report item
	// pertains to.
	Name summarize.Name `json:"name" yaml:"name"`
	// Before is what the API summary used to look like.
	Before string `json:"before,omitempty" yaml:"before,omitempty"`
	// After is what the API summary looks like now.
	After string `json:"after,omitempty" yaml:"after,omitempty"`
	// Conclusion is the finding.
	Conclusion Classification `json:"conclusion" yaml:"conclusion"`
}

func (r ReportItem) IsAdd() bool {
	return r.Before == "" && r.After != ""
}

func (r ReportItem) IsRemove() bool {
	return r.Before != "" && r.After == ""
}

func (r ReportItem) IsChange() bool {
	return r.Before != "" && r.After != ""
}

// Report is a top-level wrapper for the API diff result.
type Report struct {
	// ApiDiff has the report items for each individual change of the API
	// surface for a FIDL library.
	ApiDiff []ReportItem `json:"api_diff,omitempty" yaml:"api_diff,omitempty"`

	// backfillIndexes is a list of indexes into ApiDiff which have a
	// classification of Undetermined.
	//
	// These reportItems could not have been classified at the point that they
	// were seen in the summary because there was not enough information to do
	// so.  Instead, we remember their indexes here, and when we eventually
	// process the parent declaration we get enough info to classify, and only
	// then go back to them to finish the classification.
	//
	// A report that is "finalized" (ready to write out) *must* have this value
	// set to `nil`.  This is done by caling `BackfillForParentStrictness` at
	// some point while processing the report.
	backfillIndexes []int
}

// BackfillForParentStrictness backfills all ApiDiff indexes based on the
// appropriate strictness.
func (r *Report) BackfillForParentStrictness(isStrict bool) {
	for _, i := range r.backfillIndexes {
		// Get a pointer to the element so it can be mutated in place.
		elem := &r.ApiDiff[i]
		if elem.Conclusion != Undetermined {
			panic(fmt.Sprintf(
				"BackfillForParentStrictness: found a determined report in a list of backfill indexes: report: %+v",
				*r))
		}
		if isStrict {
			elem.Conclusion = APIBreaking
		} else {
			elem.Conclusion = SourceCompatible
		}
	}
	r.backfillIndexes = nil
}

// readTextReport reads the API diff report in text/yaml format from the
// given reader.
func readTextReport(r io.Reader) (Report, error) {
	var ret Report
	d := yaml.NewDecoder(r)
	d.SetStrict(true)
	if err := d.Decode(&ret); err != nil {
		return Report{}, fmt.Errorf("while reading as text: %w", err)
	}
	return ret, nil
}

func (r *Report) addToDiff(rep ReportItem) {
	if rep.Conclusion == 0 {
		panic(fmt.Sprintf("Unset conclusion: %+v", rep))
	}
	r.ApiDiff = append(r.ApiDiff, rep)
}

// WriteJSON is a format function that writes JSON format from the
// given report items.
func (r Report) WriteJSON(w io.Writer) error {
	if len(r.backfillIndexes) != 0 {
		panic(fmt.Sprintf("Report.WriteJSON: programming error, backfillIndexes = %v", r.backfillIndexes))
	}
	e := json.NewEncoder(w)
	e.SetEscapeHTML(false)
	e.SetIndent("", "  ")
	if err := e.Encode(r); err != nil {
		return fmt.Errorf("while writing JSON: %w", err)
	}
	return nil
}

// WriteText is a format function that writes the text format of the
// given report items.
func (r Report) WriteText(w io.Writer) error {
	if len(r.backfillIndexes) != 0 {
		panic(fmt.Sprintf("Report.WriteJSON: programming error, backfillIndexes = %v, report: %+v",
			r.backfillIndexes, r))
	}
	e := yaml.NewEncoder(w)
	if err := e.Encode(r); err != nil {
		return fmt.Errorf("while writing JSON: %w", err)
	}
	return nil
}

// add processes a single added ElementStr.
func (r *Report) add(item *summarize.ElementStr) {
	ret := ReportItem{
		Name:  item.Name,
		After: item.String(),
	}
	// TODO: compress this table if possible after all diffs have been
	// accounted for.
	switch item.Kind {
	case "bits", "enum", "struct", "library", "const",
		"table", "union", "protocol", "alias":
		ret.Conclusion = SourceCompatible
	case "enum/member", "union/member":
		// The conclusion here depends on whether the enclosing declaration is
		// strict or flexible, and whether that enclosing declaration is used.
		// Defer the conclusion until we get to processing the enclosing
		// declaration.
		ret.Conclusion = Undetermined
		r.backfillIndexes = append(r.backfillIndexes, len(r.ApiDiff))
	case "struct/member":
		// Breaks Rust initialization.
		ret.Conclusion = APIBreaking
	case "table/member", "bits/member":
		ret.Conclusion = SourceCompatible
	case "protocol/member":
		ret.Conclusion = Transitionable
	default:
		panic(fmt.Sprintf("Report.add: unknown kind: %+v", item))
	}
	r.addToDiff(ret)
}

// remove processes a single removed ElementStr
func (r *Report) remove(item *summarize.ElementStr) {
	ret := ReportItem{
		Name:   item.Name,
		Before: item.String(),
	}
	// TODO: compress this table if possible after all diffs have been
	// accounted for.
	switch item.Kind {
	case "library", "const", "bits", "enum", "struct",
		"table", "union", "protocol", "alias",
		"struct/member", "table/member", "bits/member",
		"enum/member", "union/member", "protocol/member":
		ret.Conclusion = APIBreaking
	default:
		panic(fmt.Sprintf("Report.remove: unknown kind: %+v", item))
	}
	r.addToDiff(ret)
}

func (r *Report) compare(before, after *summarize.ElementStr) {
	if *before == *after {
		// No change
		return
	}
	beforeStr := before.String()
	afterStr := after.String()
	ret := ReportItem{
		Name:   after.Name,
		Before: beforeStr,
		After:  afterStr,
	}
	// 'defer r.addToDiff(ret)` wouldn't work, because it would bind the *current*
	// value of ret to the function call, and we want the final value to be
	// used.
	defer func() {
		r.addToDiff(ret)
	}()
	if before.Kind != after.Kind {
		ret.Conclusion = APIBreaking
		return
	}
	switch after.Kind {
	case "const", "struct/member", "table/member", "union/member":
		ret.Conclusion = APIBreaking
	case "bits", "enum":
		switch {
		// Underlying type change.
		case before.Decl != after.Decl:
			ret.Conclusion = APIBreaking
		case before.IsStrict() != after.IsStrict():
			ret.Conclusion = Transitionable
		case beforeStr != afterStr: // Type change
			ret.Conclusion = APIBreaking
		}
	case "struct", "table", "union":
		switch {
		case before.Resourceness != after.Resourceness:
			ret.Conclusion = APIBreaking
		default:
			ret.Conclusion = Transitionable
		}
	case "protocol/member":
		ret.Conclusion = APIBreaking
	case "protocol":
		fallthrough
	default:
		panic(fmt.Sprintf(
			"Report.compare: kind not handled: %v; this is a programer error",
			after.Kind))
	}
	if beforeStr == afterStr {
		panic(fmt.Sprintf(
			"Report.compare: beforeStr == afterStr - programming error: before: %+v, after: %+v",
			before, after))
	}
}
