// Copyright 2019 The Go 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 myers

import (
	"fmt"
	"strings"

	"golang.org/x/tools/internal/lsp/diff"
)

type Unified struct {
	From, To string
	Hunks    []*Hunk
}

type Hunk struct {
	FromLine int
	ToLine   int
	Lines    []Line
}

type Line struct {
	Kind    diff.OpKind
	Content string
}

const (
	edge = 3
	gap  = edge * 2
)

func ToUnified(from, to string, lines []string, ops []*Op) Unified {
	u := Unified{
		From: from,
		To:   to,
	}
	if len(ops) == 0 {
		return u
	}
	var h *Hunk
	last := -(gap + 2)
	for _, op := range ops {
		switch {
		case op.I1 < last:
			panic("cannot convert unsorted operations to unified diff")
		case op.I1 == last:
			//direct extension
		case op.I1 <= last+gap:
			//within range of previous lines, add the joiners
			addEqualLines(h, lines, last, op.I1)
		default:
			//need to start a new hunk
			if h != nil {
				// add the edge to the previous hunk
				addEqualLines(h, lines, last, last+edge)
				u.Hunks = append(u.Hunks, h)
			}
			h = &Hunk{
				FromLine: op.I1 + 1,
				ToLine:   op.J1 + 1,
			}
			// add the edge to the new hunk
			delta := addEqualLines(h, lines, op.I1-edge, op.I1)
			h.FromLine -= delta
			h.ToLine -= delta
		}
		last = op.I1
		switch op.Kind {
		case diff.Delete:
			for i := op.I1; i < op.I2; i++ {
				h.Lines = append(h.Lines, Line{Kind: diff.Delete, Content: lines[i]})
				last++
			}
		case diff.Insert:
			for _, c := range op.Content {
				h.Lines = append(h.Lines, Line{Kind: diff.Insert, Content: c})
			}
		default:
			// all other op types ignored
		}
	}
	if h != nil {
		// add the edge to the final hunk
		addEqualLines(h, lines, last, last+edge)
		u.Hunks = append(u.Hunks, h)
	}
	return u
}

func addEqualLines(h *Hunk, lines []string, start, end int) int {
	delta := 0
	for i := start; i < end; i++ {
		if i < 0 {
			continue
		}
		if i >= len(lines) {
			return delta
		}
		h.Lines = append(h.Lines, Line{Kind: diff.Equal, Content: lines[i]})
		delta++
	}
	return delta
}

func (u Unified) Format(f fmt.State, r rune) {
	if len(u.Hunks) == 0 {
		return
	}
	fmt.Fprintf(f, "--- %s\n", u.From)
	fmt.Fprintf(f, "+++ %s\n", u.To)
	for _, hunk := range u.Hunks {
		fromCount, toCount := 0, 0
		for _, l := range hunk.Lines {
			switch l.Kind {
			case diff.Delete:
				fromCount++
			case diff.Insert:
				toCount++
			default:
				fromCount++
				toCount++
			}
		}
		fmt.Fprint(f, "@@")
		if fromCount > 1 {
			fmt.Fprintf(f, " -%d,%d", hunk.FromLine, fromCount)
		} else {
			fmt.Fprintf(f, " -%d", hunk.FromLine)
		}
		if toCount > 1 {
			fmt.Fprintf(f, " +%d,%d", hunk.ToLine, toCount)
		} else {
			fmt.Fprintf(f, " +%d", hunk.ToLine)
		}
		fmt.Fprint(f, " @@\n")
		for _, l := range hunk.Lines {
			switch l.Kind {
			case diff.Delete:
				fmt.Fprintf(f, "-%s", l.Content)
			case diff.Insert:
				fmt.Fprintf(f, "+%s", l.Content)
			default:
				fmt.Fprintf(f, " %s", l.Content)
			}
			if !strings.HasSuffix(l.Content, "\n") {
				fmt.Fprintf(f, "\n\\ No newline at end of file\n")
			}
		}
	}
}
