package printer

import (
	"fmt"
	"net"
	"strconv"
	"strings"

	"github.com/fatih/color"
	"github.com/xgadget-lab/nexttrace/trace"
)

func RealtimePrinterWithRouter(res *trace.Result, ttl int) {
	fmt.Printf("%s  ", color.New(color.FgHiYellow, color.Bold).Sprintf("%-2d", ttl+1))

	// 去重
	var latestIP string
	tmpMap := make(map[string][]string)
	for i, v := range res.Hops[ttl] {
		if v.Address == nil && latestIP != "" {
			tmpMap[latestIP] = append(tmpMap[latestIP], fmt.Sprintf("%s ms", "*"))
			continue
		} else if v.Address == nil {
			continue
		}

		if _, exist := tmpMap[v.Address.String()]; !exist {
			tmpMap[v.Address.String()] = append(tmpMap[v.Address.String()], strconv.Itoa(i))
			// 首次进入
			if latestIP == "" {
				for j := 0; j < i; j++ {
					tmpMap[v.Address.String()] = append(tmpMap[v.Address.String()], fmt.Sprintf("%s ms", "*"))
				}
			}
			latestIP = v.Address.String()
		}

		tmpMap[v.Address.String()] = append(tmpMap[v.Address.String()], fmt.Sprintf("%.2f ms", v.RTT.Seconds()*1000))
	}

	if latestIP == "" {
		fmt.Fprintf(color.Output, "%s\n",
			color.New(color.FgWhite, color.Bold).Sprintf("*"),
		)
		return
	}

	var blockDisplay = false
	for ip, v := range tmpMap {
		if blockDisplay {
			fmt.Printf("%4s", "")
		}
		if net.ParseIP(ip).To4() == nil {
			fmt.Fprintf(color.Output, "%s",
				color.New(color.FgWhite, color.Bold).Sprintf("%-25s", ip),
			)
		} else {
			fmt.Fprintf(color.Output, "%s",
				color.New(color.FgWhite, color.Bold).Sprintf("%-15s", ip),
			)
		}

		i, _ := strconv.Atoi(v[0])

		if res.Hops[ttl][i].Geo.Asnumber != "" {
			fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("AS%-6s", res.Hops[ttl][i].Geo.Asnumber))
		} else {
			fmt.Printf(" %-8s", "*")
		}

		if net.ParseIP(ip).To4() != nil {
			whoisFormat := strings.Split(res.Hops[ttl][i].Geo.Whois, "-")
			if len(whoisFormat) > 1 {
				whoisFormat[0] = strings.Join(whoisFormat[:2], "-")
			}

			if whoisFormat[0] != "" {
				whoisFormat[0] = "[" + whoisFormat[0] + "]"
			}
			fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("%-16s", whoisFormat[0]))
		}

		if res.Hops[ttl][i].Geo.Country == "" {
			res.Hops[ttl][i].Geo.Country = "LAN Address"
		}

		if net.ParseIP(ip).To4() != nil {

			fmt.Fprintf(color.Output, " %s %s %s %s %s\n    %s   ",
				color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Country),
				color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Prov),
				color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.City),
				color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.District),
				fmt.Sprintf("%-6s", res.Hops[ttl][i].Geo.Owner),
				color.New(color.FgHiBlack, color.Bold).Sprintf("%-39s", res.Hops[ttl][i].Hostname),
			)
		} else {
			fmt.Fprintf(color.Output, " %s %s %s %s %s\n    %s   ",
				color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Country),
				color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Prov),
				color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.City),
				color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.District),
				fmt.Sprintf("%-6s", res.Hops[ttl][i].Geo.Owner),
				color.New(color.FgHiBlack, color.Bold).Sprintf("%-32s", res.Hops[ttl][i].Hostname),
			)
		}

		for j := 1; j < len(v); j++ {
			if len(v) == 2 || j == 1 {
				fmt.Fprintf(color.Output, "%s",
					color.New(color.FgHiCyan, color.Bold).Sprintf("%s", v[j]),
				)
			} else {
				fmt.Fprintf(color.Output, " / %s",
					color.New(color.FgHiCyan, color.Bold).Sprintf("%s", v[j]),
				)
			}
		}
		i = 0
		fmt.Println()
		if res.Hops[ttl][i].Geo != nil && !blockDisplay {
			fmt.Fprintf(color.Output, "%s   %s %s %s   %s\n",
				color.New(color.FgWhite, color.Bold).Sprintf("-"),
				color.New(color.FgHiYellow, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Prefix),
				color.New(color.FgWhite, color.Bold).Sprintf("路由表"),
				color.New(color.FgHiCyan, color.Bold).Sprintf("Beta"),
				color.New(color.FgWhite, color.Bold).Sprintf("-"),
			)
			GetRouter(&res.Hops[ttl][i].Geo.Router, "AS"+res.Hops[ttl][i].Geo.Asnumber)
		}
		blockDisplay = true
	}
}

func GetRouter(r *map[string][]string, node string) {
	routeMap := *r
	for _, v := range routeMap[node] {
		if len(routeMap[v]) != 0 {
			fmt.Fprintf(color.Output, "    %s %s %s\n",
				color.New(color.FgWhite, color.Bold).Sprintf("%s", routeMap[v][0]),
				color.New(color.FgWhite, color.Bold).Sprintf("%s", v),
				color.New(color.FgHiBlue, color.Bold).Sprintf("%s", node),
			)
		} else {
			fmt.Fprintf(color.Output, "    %s %s\n",
				color.New(color.FgWhite, color.Bold).Sprintf("%s", v),
				color.New(color.FgHiBlue, color.Bold).Sprintf("%s", node),
			)
		}

	}
}
