package cointop

import (
	"fmt"
	"math"
	"strings"
	"time"

	fcolor "github.com/fatih/color"

	"github.com/cointop-sh/cointop/pkg/api/types"
	"github.com/cointop-sh/cointop/pkg/humanize"
	"github.com/cointop-sh/cointop/pkg/pad"
	"github.com/cointop-sh/cointop/pkg/ui"
	log "github.com/sirupsen/logrus"
)

// MarketbarView is structure for marketbar view
type MarketbarView = ui.View

// NewMarketbarView returns a new marketbar view
func NewMarketbarView() *MarketbarView {
	return ui.NewView("marketbar")
}

// UpdateMarketbar updates the market bar view
func (ct *Cointop) UpdateMarketbar() error {
	log.Debug("UpdateMarketbar()")
	maxX := ct.Width()
	logo := "❯❯❯cointop"
	if ct.colorschemeName == "cointop" {
		Green := fcolor.New(fcolor.FgGreen).SprintFunc()
		Cyan := fcolor.New(fcolor.FgCyan).SprintFunc()
		logo = fmt.Sprintf("%s%s%s%s", Green("❯"), Cyan("❯"), Green("❯"), Cyan("cointop"))
	}
	var content string

	if ct.IsPortfolioVisible() {
		ct.State.marketBarHeight = 1
		total := ct.GetPortfolioTotal()
		totalstr := humanize.Monetaryf(total, 2)
		if !(ct.State.currencyConversion == "BTC" || ct.State.currencyConversion == "ETH" || total < 1) {
			total = math.Round(total*1e2) / 1e2
			totalstr = humanize.Monetaryf(total, 2)
		}
		if ct.State.compactNotation {
			totalstr = humanize.ScaleNumericf(total, 3)
		}

		timeframe := ct.State.selectedChartRange
		chartname := ct.SelectedCoinName()
		var charttitle string
		if chartname == "" {
			chartname = "Portfolio"
			charttitle = ct.colorscheme.MarketBarLabelActive(chartname)
		} else {
			charttitle = fmt.Sprintf("Portfolio - %s", ct.colorscheme.MarketBarLabelActive(chartname))
		}

		var percentChange24H float64
		for _, p := range ct.GetPortfolioSlice() {
			n := (p.Balance / total) * p.PercentChange24H
			if math.IsNaN(n) {
				continue
			}
			percentChange24H += n
		}

		color24h := ct.colorscheme.MarketbarSprintf()
		arrow := ""
		if percentChange24H > 0 {
			color24h = ct.colorscheme.MarketbarChangeUpSprintf()
			arrow = "▲"
		}
		if percentChange24H < 0 {
			color24h = ct.colorscheme.MarketbarChangeDownSprintf()
			arrow = "▼"
		}
		percentChange24Hstr := color24h(fmt.Sprintf("%.2f%%%s", percentChange24H, arrow))

		chartInfo := ""
		if !ct.State.hideChart {
			chartInfo = fmt.Sprintf(
				"[ Chart: %s %s ] ",
				charttitle,
				timeframe,
			)
		}

		totalstr = fmt.Sprintf("%s%s", ct.CurrencySymbol(), totalstr)
		if ct.State.hidePortfolioBalances {
			totalstr = HiddenBalanceChars
			percentChange24Hstr = HiddenBalanceChars
		}

		content = fmt.Sprintf(
			"%sTotal Portfolio Value %s: %s • 24H: %s",
			chartInfo,
			ct.State.currencyConversion,
			ct.colorscheme.MarketBarLabelActive(totalstr),
			percentChange24Hstr,
		)
	} else {
		ct.State.marketBarHeight = 1
		if ct.Width() < 125 {
			ct.State.marketBarHeight = 2
		}

		var market types.GlobalMarketData
		var err error
		cachekey := ct.CompositeCacheKey("market", "", ct.State.currencyConversion, "")
		cached, found := ct.cache.Get(cachekey)

		if found {
			// cache hit
			var ok bool
			market, ok = cached.(types.GlobalMarketData)
			if ok {
				log.Debug("UpdateMarketbar() soft cache hit")
			}
		}

		if market.TotalMarketCapUSD == 0 {
			market, err = ct.api.GetGlobalMarketData(ct.State.currencyConversion)
			if err != nil {
				if ct.filecache != nil {
					ct.filecache.Get(cachekey, &market)
				}
			}

			ct.cache.Set(cachekey, market, 10*time.Second)
			if ct.filecache != nil {
				go func() {
					ct.filecache.Set(cachekey, market, 24*time.Hour)
				}()
			}
		}

		timeframe := ct.State.selectedChartRange
		chartname := ct.SelectedCoinName()
		if chartname == "" {
			chartname = "Global"
		}

		chartInfo := ""
		if !ct.State.hideChart {
			chartInfo = fmt.Sprintf(
				"[ Chart: %s %s] ",
				ct.colorscheme.MarketBarLabelActive(chartname),
				timeframe,
			)
		}

		separator1 := "•"
		separator2 := "•"
		offset := strings.Repeat(" ", 12)
		if ct.Width() < 105 {
			separator1 = "\n" + offset
		} else if ct.Width() < 125 {
			separator2 = "\n" + offset
		}

		marketCapStr := humanize.Monetaryf(market.TotalMarketCapUSD, 0)
		volumeStr := humanize.Monetaryf(market.Total24HVolumeUSD, 0)
		if ct.State.compactNotation {
			marketCapStr = humanize.ScaleNumericf(market.TotalMarketCapUSD, 3)
			volumeStr = humanize.ScaleNumericf(market.Total24HVolumeUSD, 3)
		}

		content = fmt.Sprintf(
			"%sGlobal %s ▶ Market Cap: %s %s 24H Volume: %s %s BTC Dominance: %.2f%%",
			chartInfo,
			ct.State.currencyConversion,
			fmt.Sprintf("%s%s", ct.CurrencySymbol(), marketCapStr),
			separator1,
			fmt.Sprintf("%s%s", ct.CurrencySymbol(), volumeStr),
			separator2,
			market.BitcoinPercentageOfMarketCap,
		)
	}

	content = fmt.Sprintf("%s %s", logo, content)
	content = pad.Right(content, maxX, " ")
	content = ct.colorscheme.Marketbar(content)

	ct.UpdateUI(func() error {
		return ct.Views.Marketbar.Update(content)
	})

	return nil
}
