package tala

import (
	"sort"
	"strconv"
)

//牌序- K, Q, J, 10, 9, 8, 7, 6, 5, 4, 3, 2, A
//方片- 51,50,49,48,47,46,45,44,43,42,41,40,39
//红桃- 38,37,36,35,34,33,32,31,30,29,28,27,26
//梅花- 25,24,23,22,21,20,19,18,17,16,15,14,13
//黑桃- 12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0

const (
	TaLaNil       int = iota //nil
	ColorStraight            //1 同花顺
	Triple                   //2 三张
)

// Color 黑桃0 梅花1 紅桃2 方片3
func Color(c int32) int {
	return int(c) / PER_CARD_COLOR_MAX
}

func Value(c int32) int {
	value := int(c+1) % PER_CARD_COLOR_MAX
	if value == 0 {
		value = PER_CARD_COLOR_MAX
	}
	return value
}

func ValueStr(c int32) string {
	if c == InvalideCard {
		return ""
	}
	str := ""
	value := strconv.Itoa(Value(c))
	switch Color(c) {
	case 0:
		str = "黑桃"
	case 1:
		str = "梅花"
	case 2:
		str = "紅桃"
	case 3:
		str = "方片"
	}
	return str + value
}

func IsStraight(cards []int32) bool { //顺子
	if len(cards) < 3 || len(cards) > HandCardNum {
		return false
	}
	tmpCards := []int{}
	for _, card := range cards {
		tmpCards = append(tmpCards, Value(card))
	}
	sort.Ints(tmpCards)
	for i := 0; i < len(tmpCards)-1; i++ {
		card := tmpCards[i]
		nextCard := tmpCards[i+1]
		if nextCard-card != 1 { //不相邻
			return false
		}
	}
	return true
}

func IsColorStraight(cards []int32) bool { //同花顺子
	// 先是顺子
	if !IsStraight(cards) {
		return false
	}
	c := Color(cards[0])
	for _, card := range cards {
		if c != Color(card) {
			return false
		}
	}
	return true
}

func IsTriple(cards []int32) bool { //三张
	if len(cards) < 3 || len(cards) > 4 { // 3张或者4张
		return false
	}
	switch len(cards) {
	case 3:
		if Value(cards[0]) != Value(cards[1]) {
			return false
		}
		if Value(cards[1]) != Value(cards[2]) {
			return false
		}
		return true
	case 4:
		if Value(cards[0]) != Value(cards[1]) {
			return false
		}
		if Value(cards[1]) != Value(cards[2]) {
			return false
		}
		if Value(cards[2]) != Value(cards[3]) {
			return false
		}
		return true
	}
	return false
}

func CanChi(cards []int32, chiCard int32, excludeCards []int32) (bool, []int32) { //可吃
	chi2pPhom := []int32{chiCard}
	if chiCard == InvalideCard {
		return false, chi2pPhom
	}
	cpCards := []int32{}
	for _, card := range cards {
		if card != InvalideCard {
			cpCards = append(cpCards, card)
		}
	}
	if len(cpCards) == 0 {
		return false, chi2pPhom
	}
	n := 0
	tmp := []int32{}
	for _, card := range cpCards {
		if Value(chiCard) == Value(card) && !InSliceInt32(excludeCards, card) {
			n++
			tmp = append(tmp, card)
		}
	}
	if n >= 2 { //找到两张以上牌值相同的，可以吃
		for _, card := range tmp {
			chi2pPhom = append(chi2pPhom, card)
		}
		return true, chi2pPhom
	}
	chi2pPhom = []int32{chiCard}
	min1 := false
	min2 := false
	minPhom := []int32{}
	mid1 := false
	mid2 := false
	midPhom := []int32{}
	max1 := false
	max2 := false
	maxPhom := []int32{}

	for _, card := range cpCards {
		if Color(chiCard) == Color(card) && !InSliceInt32(excludeCards, card) {
			//最小
			if chiCard+1 == card {
				minPhom = append(minPhom, card)
				min1 = true
			}
			if chiCard+2 == card {
				minPhom = append(minPhom, card)
				min2 = true
			}
			if min1 && min2 {
				for _, c := range minPhom {
					chi2pPhom = append(chi2pPhom, c)
				}
				return true, chi2pPhom
			}
			//中间
			if chiCard+1 == card {
				midPhom = append(midPhom, card)
				mid1 = true
			}
			if chiCard-1 == card {
				midPhom = append(midPhom, card)
				mid2 = true
			}
			if mid1 && mid2 {
				for _, c := range midPhom {
					chi2pPhom = append(chi2pPhom, c)
				}
				return true, chi2pPhom
			}
			//最大
			if chiCard-1 == card {
				maxPhom = append(maxPhom, card)
				max1 = true
			}
			if chiCard-2 == card {
				maxPhom = append(maxPhom, card)
				max2 = true
			}
			if max1 && max2 {
				for _, c := range maxPhom {
					chi2pPhom = append(chi2pPhom, c)
				}
				return true, chi2pPhom
			}
		}
	}
	return false, chi2pPhom
}

func GetCardsValue(cards []int32) int {
	cardValue := 0
	for _, card := range cards {
		if card != InvalideCard {
			cardValue += Value(card)
		}
	}
	return cardValue
}

// 尝试组合phom
func TryPhom(cards, chiCards []int32) ([]int32, [][]int32) { //胡
	cpCards := []int32{}
	phomCards := [][]int32{}
	for _, card := range cards {
		if card != InvalideCard {
			cpCards = append(cpCards, card)
		}
	}
	if len(cpCards) == 0 {
		return cpCards, phomCards
	}
	cardValue := GetCardsValue(cards)
	tmpPhoms := [][]int32{}
	var TryOpPhom func([]int32)

	TryOpPhom = func(cs []int32) {
		if len(cs) == 0 {
			return
		}
		cp := []int32{}
		for _, i2 := range cs {
			if i2 != InvalideCard {
				cp = append(cp, i2)
			}
		}
		//fmt.Println("===2===", cp)
		phoms := needPhom(cp)
		if len(phoms) != 0 {
			//fmt.Println("===4===", phoms)
			for _, phom := range phoms {
				for _, card := range phom {
					for i := 0; i < len(cp); i++ {
						if cp[i] == card {
							cp = append(cp[:i], cp[i+1:]...)
							i--
						}
					}
				}
				tmpCp := []int32{}
				for _, tmp := range cp {
					tmpCp = append(tmpCp, tmp)
				}
				tmpPhoms = append(tmpPhoms, phom)

				TryOpPhom(tmpCp)

				//fmt.Println("===3===", tmpCp, tmpPhoms)
				if GetCardsValue(tmpCp) < cardValue && !InSliceASliceB(tmpCp, chiCards) { //是不是最优解 //吃过的牌不能留在手牌里
					cardValue = GetCardsValue(cp)
					phomCards = [][]int32{}
					for _, tmpPhom := range tmpPhoms {
						if len(tmpPhom) > 0 {
							tmp := []int32{}
							for _, c := range tmpPhom {
								tmp = append(tmp, c)
							}
							phomCards = append(phomCards, tmp)
						}
					}
				}
				cp = []int32{} //回退下 next
				for _, card := range cs {
					cp = append(cp, card)
				}
				tmpPhoms = append(tmpPhoms[:len(tmpPhoms)-1])
			}
		}
		return
	}

	TryOpPhom(cpCards)
	//fmt.Println("===1===", phomCards)
	for _, phom := range phomCards {
		for _, card := range phom {
			for i, cpcard := range cpCards {
				if card == cpcard {
					cpCards = append(cpCards[:i], cpCards[i+1:]...)
					i--
					break
				}
			}
		}
	}
	return cpCards, phomCards
}

// b中元素是否在a里面
func InSliceASliceB(a, b []int32) bool {
	for _, bi := range b {
		if InSliceInt32(a, bi) {
			return true
		}
	}
	return false
}

// 有所有的同花顺组合 或者 有所有的点数相同的组合
func needPhom(cards []int32) [][]int32 { //胡
	tmps := [][]int32{}
	haveColorStraights, colorStraights := needColorStraight(cards)
	haveTriples, triples := needTriple(cards)
	if haveColorStraights || haveTriples { //有所有的同花顺组合 或者 有所有的点数相同的组合
		if haveColorStraights {
			for _, straight := range colorStraights {
				tmps = append(tmps, straight)
			}
		}
		if haveTriples {
			for _, triple := range triples {
				tmps = append(tmps, triple)
			}
		}
	}
	return tmps
}

// 找所有相同点数的三张
func needTriple(cards []int32) (bool, [][]int32) {
	haveNeed := false
	needCards := [][]int32{}
	if len(cards) != 0 {
		mapTriple := make(map[int32][]int32)
		for _, card := range cards {
			if card != InvalideCard {
				mapTriple[int32(Value(card))] = append(mapTriple[int32(Value(card))], card)
			}
		}
		if len(mapTriple) > 0 {
			for _, tripleCards := range mapTriple {
				if len(tripleCards) == 3 {
					haveNeed = true
					needCards = append(needCards, tripleCards)
				}
				if len(tripleCards) == 4 {
					haveNeed = true
					needCards = append(needCards, tripleCards)
					for _, card := range tripleCards {
						tmps := []int32{}
						for _, tmp := range tripleCards {
							if card != tmp {
								tmps = append(tmps, tmp)
							}
						}
						if len(tmps) > 0 {
							needCards = append(needCards, tmps)
						}
					}
				}
			}
		}
	}
	return haveNeed, needCards
}

// 所有的同花顺
func needColorStraight(cards []int32) (bool, [][]int32) {
	haveNeed := false
	needCards := [][]int32{}
	if len(cards) != 0 {
		sliceCS := [4][]int32{} //color-card
		for _, card := range cards {
			if card != InvalideCard {
				sliceCS[Color(card)] = append(sliceCS[Color(card)], card)
			}
		}
		for _, colorCards := range sliceCS {
			if len(colorCards) > 0 {
				sort.Slice(colorCards, func(i, j int) bool {
					if Value(colorCards[i]) > Value(colorCards[j]) {
						return false
					}
					return true
				})
				for i := len(colorCards); i > 2; i-- {
					tmps := FindStraightWithWidth(i, colorCards)
					if len(tmps) > 0 {
						haveNeed = true
						for _, tmp := range tmps {
							needCards = append(needCards, tmp)
						}
					}
				}
			}
		}
	}
	return haveNeed, needCards
}

// 找一个固定长度的顺子 (2,3,4,5,6) 3-> [2,3,4]
func FindOneStraightWithWidth(n int, pairs []int32) []int32 {
	if len(pairs) == 0 {
		return nil
	}
	lastKey := pairs[0]
	tempPair := []int32{lastKey}
	if n == 1 {
		return tempPair
	}
	for i := 1; i < len(pairs); i++ {
		if pairs[i]-lastKey == 1 {
			tempPair = append(tempPair, pairs[i])
		} else {
			tempPair = []int32{pairs[i]}
		}
		if len(tempPair) == n {
			break
		}
		lastKey = pairs[i]
	}
	if len(tempPair) == n {
		return tempPair
	}
	return nil
}

// 找多个固定长度的顺子(2,3,4,5,6) 3-> [[2,3,4][3,4,5][4,5,6]]
func FindStraightWithWidth(n int, pairs []int32) [][]int32 {
	if len(pairs) == 0 || n < 2 {
		return nil
	}
	var tempPairs [][]int32
	lastKey := pairs[0]
	tempPair := []int32{lastKey}
	for i := 1; i < len(pairs); i++ {
		if pairs[i]-lastKey == 1 {
			tempPair = append(tempPair, pairs[i])
		} else {
			tempPair = []int32{pairs[i]}
		}
		if len(tempPair) == n {
			tempPairs = append(tempPairs, tempPair)
			tempPair = []int32{}
			for j := n - 1; j > 0; j-- {
				tempPair = append(tempPair, pairs[i-j+1])
			}
		}
		lastKey = pairs[i]
	}
	return tempPairs
}

func DelSliceInt32(sl []int32, v int32) []int32 {
	index := -1
	for key, value := range sl {
		if value == v {
			index = key
			break
		}
	}
	if index != -1 {
		sl = append(sl[:index], sl[index+1:]...)
	}
	return sl
}

func InSliceInt32(sl []int32, v int32) bool {
	for _, vv := range sl {
		if vv == v {
			return true
		}
	}
	return false
}
