// Copyright 2023 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//  1. Redistributions of source code must retain the above copyright notice, this
//     list of conditions and the following disclaimer.
//
//  2. Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//  3. Neither the name of the copyright holder nor the names of its
//     contributors may be used to endorse or promote products derived from
//     this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Package progressbar provides functions for drawing Unicode progress bars to
// the terminal
package progressbar

import (
	"bytes"
	"fmt"
	"io"
	"math"
	"strings"
	"sync"
	"time"

	"dawn.googlesource.com/dawn/tools/src/term"
)

// Defaults for the Config
const (
	DefaultRefreshRate = time.Millisecond * 100
	DefaultWidth       = 50
	DefaultANSIColors  = true
)

// Config holds configuration options for a ProgressBar
type Config struct {
	RefreshRate time.Duration
	Width       int
	ANSIColors  bool
}

// Color is an enumerator of colors
type Color int

// Color enumerators
const (
	White Color = iota
	Red
	Green
	Yellow
	Blue
	Magenta
	Cyan
)

// Segment describes a single segment of the ProgressBar
type Segment struct {
	Count       int
	Color       Color
	Transparent bool
	Bold        bool
}

// Status holds the updated data of the ProgressBar
type Status struct {
	Total    int
	Segments []Segment
}

// ProgressBar is an interface for progress bars.
type ProgressBar interface {
	// Update updates the ProgressBar with the given status
	Update(s Status)
	// Stop stops drawing the progress bar.
	// Once called, the ProgressBar must not be used.
	Stop()
}

type Build func(out io.Writer, cfg *Config) ProgressBar

// New returns a new ProgressBar that streams output to out.
// Selects between realProgressBar and StubProgressBar automatically depending
// on if the output will be displayed in the terminal correctly.
// Call ProgressBar.Stop() once finished.
func New(out io.Writer, cfg *Config) ProgressBar {
	if !term.CanUseAnsiEscapeSequences() {
		return NewStubProgressBar(out, cfg)
	}

	return newRealProgressBar(out, cfg)
}

// NewRealProgressBar constructs and returns a realProgressBar.
// Does not check if the terminal supports the needed escape characters, which
// is why it is not exposed outside the package, use New() instead.
func newRealProgressBar(out io.Writer, cfg *Config) ProgressBar {
	p := &realProgressBar{
		out:  out,
		c:    make(chan Status, 64),
		done: make(chan struct{}),
	}
	if cfg != nil {
		p.Config = *cfg
	} else {
		p.ANSIColors = DefaultANSIColors
	}
	if p.RefreshRate == 0 {
		p.RefreshRate = DefaultRefreshRate
	}
	if p.Width == 0 {
		p.Width = DefaultWidth
	}
	go func() {
		defer close(p.done)
		var status *Status
		dirty := false
		frame := 0
		t := time.NewTicker(p.RefreshRate)
		defer t.Stop()
		for {
			select {
			case s, ok := <-p.c:
				if !ok {
					if status != nil {
						if dirty {
							status.Draw(out, p.Width, p.ANSIColors, frame)
						}
						if p.ANSIColors {
							fmt.Fprintln(out)
						}
					}
					return
				}
				status = &s
				dirty = true
			case <-t.C:
				if status != nil {
					status.Draw(out, p.Width, p.ANSIColors, frame)
					frame++
					dirty = false
				}
			}
		}
	}()
	return p
}

// NewStubProgressBar returns a new StubProgressBar, used in tests to guarantee
// the type of ProgressBar returned.
// Note: In production code, use New() instead.
func NewStubProgressBar(_ io.Writer, _ *Config) ProgressBar {
	return &StubProgressBar{}
}

// StubProgressBar is a ProgressBar that does nothing, used in environments that
// don't support the control characters needed or when testing to avoid spamming
// output.
type StubProgressBar struct{}

func (p *StubProgressBar) Update(s Status) {}

func (p *StubProgressBar) Stop() {}

// realProgressBar writes out a string with an ANSI-colored progress bar,
// providing realtime information about the status of the CTS run.
// Note: Does not work if !isatty or if running on windows.
type realProgressBar struct {
	Config
	out      io.Writer
	c        chan Status
	done     chan struct{}
	stopOnce sync.Once
}

func (p *realProgressBar) Update(s Status) {
	p.c <- s
}

func (p *realProgressBar) Stop() {
	p.stopOnce.Do(func() {
		close(p.c)
	})
	<-p.done
}

// Draw draws the ProgressBar status to out
func (s Status) Draw(out io.Writer, width int, ansiColors bool, animFrame int) {
	// ANSI escape sequences
	const (
		escape       = "\u001B["
		positionLeft = escape + "0G"
		ansiReset    = escape + "0m"

		bold = escape + "1m"

		red     = escape + "31m"
		green   = escape + "32m"
		yellow  = escape + "33m"
		blue    = escape + "34m"
		magenta = escape + "35m"
		cyan    = escape + "36m"
		white   = escape + "37m"
	)

	animSymbols := []rune{'⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷'}
	blockSymbols := []rune{'▏', '▎', '▍', '▌', '▋', '▊', '▉'}

	numBlocksPrinted := 0

	buf := &bytes.Buffer{}
	fmt.Fprint(buf, "  ", string(animSymbols[animFrame%len(animSymbols)]), " [")

	numFinished := 0
	for _, seg := range s.Segments {
		if ansiColors {
			switch seg.Color {
			case Red:
				buf.WriteString(red)
			case Green:
				buf.WriteString(green)
			case Yellow:
				buf.WriteString(yellow)
			case Blue:
				buf.WriteString(blue)
			case Magenta:
				buf.WriteString(magenta)
			case Cyan:
				buf.WriteString(cyan)
			default:
				buf.WriteString(white)
			}
			if seg.Bold {
				buf.WriteString(bold)
			}
		}

		numFinished += seg.Count
		statusFrac := float64(seg.Count) / float64(s.Total)
		fNumBlocks := float64(width) * statusFrac
		numBlocks := int(math.Ceil(fNumBlocks))
		if seg.Transparent {
			if numBlocks > 0 {
				fmt.Fprint(buf, strings.Repeat(string("░"), numBlocks))
			}
		} else {
			if numBlocks > 1 {
				fmt.Fprint(buf, strings.Repeat(string("▉"), numBlocks-1))
			}
			if numBlocks > 0 {
				frac := fNumBlocks - float64(numBlocks-1)
				symbol := blockSymbols[int(math.Round(frac*float64(len(blockSymbols)-1)))]
				fmt.Fprint(buf, string(symbol))
			}
		}
		numBlocksPrinted += numBlocks
	}

	if width > numBlocksPrinted {
		fmt.Fprint(buf, strings.Repeat(string(" "), width-numBlocksPrinted))
	}
	fmt.Fprint(buf, ansiReset)
	fmt.Fprint(buf, "] ", percentage(numFinished, s.Total))

	if ansiColors {
		// move cursor to start of line so the bar is overridden next print
		fmt.Fprint(buf, positionLeft)
	} else {
		// cannot move cursor, so newline
		fmt.Fprintln(buf)
	}

	out.Write(buf.Bytes())
}

// percentage returns the percentage of n out of total as a string
func percentage(n, total int) string {
	if total == 0 {
		return "-"
	}
	f := float64(n) / float64(total)
	return fmt.Sprintf("%.1f%c", f*100.0, '%')
}
