package thirteen

import (
	"fmt"
	"sort"
)

const (
	SpecialType_0       int = iota
	CyanLongType            // 清龙
	ALongType               // 一条龙
	TwelveKingType          //十二皇族
	ThreeColorFlushType     // 三同花顺
	ThreeTheWorldType       //三分天下
	AllBigType              //全大
	AllSmallType            //全小
	SameColorType           // 凑一色
	FourThreeType           //四套三条
	FivePairsThreeType      //五对三条
	SixPairsHalfType        // 六对半
	ThreeContinuityType     // 三顺子
	ThreeColorsType         //三同花
	SpecialTypeMax
)

var SpecialTypeName = map[int]string{
	SpecialType_0:       "-",
	CyanLongType:        "清龙",
	ALongType:           "一条龙",
	TwelveKingType:      "十二皇族",
	ThreeColorFlushType: "三同花顺",
	ThreeTheWorldType:   "三分天下",
	AllBigType:          "全大",
	AllSmallType:        "全小",
	SameColorType:       "凑一色",
	FourThreeType:       "四套三条",
	FivePairsThreeType:  "五对三条",
	SixPairsHalfType:    "六对半",
	ThreeContinuityType: "三顺子",
	ThreeColorsType:     "三同花",
}

func SpecialName(n int) string {
	if n <= 0 {
		return "-"
	}
	return fmt.Sprintf("%v,%v,%v,%v", SpecialTypeName[n/1000000], PokersTypeName[n%1000000/10000], PokersTypeName[n%10000/100], PokersTypeName[n%100])
}

// CyanLong 找清龙
// 13张同花色
func CyanLong(cards [13]int, lai []int) bool {
	getLaiZiCards(cards[:], lai) // 去掉癞子牌
	// 找一个花色
	color := -1
	for _, v := range cards {
		if v < 0 {
			continue
		}
		color = ToColor(v)
		break
	}
	if color < 0 {
		return false
	}
	// 除癞子牌，其余牌同花色
	for _, v := range cards {
		if v < 0 {
			continue
		}
		if ToColor(v) != color {
			return false
		}
	}
	return true
}

// ALong 找一条龙
// 13张顺子
func ALong(cards [13]int, lai []int) bool {
	_, laiZiCards, cardsCount := remainCards(cards[:], lai)
	var n int
	for i := 0; i < 13; i++ {
		if cardsCount[i] == 0 {
			n++
		}
	}
	return n <= len(laiZiCards)
}

// 是不是顺子
// 没有牌的用癞子填充
func isFlush(cards []int) bool {
	//fmt.Printf("isFlush: %v\n", PokersShow(cards))
	if len(cards) != 3 && len(cards) != 5 {
		return false
	}
	laiZiCount := 0
	cardsCount := [20]int{}
	for _, v := range cards {
		if v < 0 {
			laiZiCount++
			continue
		}
		cardsCount[ToLogic(v)]++
	}
	//fmt.Printf("isFlush cardsCount: %v\n", cardsCount)
	if len(cards) == 3 {
		for i := 0; i < 10; i++ { // 排除QKA
			var n int
			for j := i; j < i+3; j++ {
				if cardsCount[j] == 0 {
					n++
				}
			}
			if n <= laiZiCount {
				return true
			}
		}
		// 找 A 2 3
		n := 0
		if cardsCount[0] == 0 {
			n++
		}
		if cardsCount[1] == 0 {
			n++
		}
		if cardsCount[12] == 0 {
			n++
		}
		if n <= laiZiCount {
			return true
		}
	} else {
		for i := 0; i < 9; i++ {
			var n int
			for j := i; j < i+5; j++ {
				if cardsCount[j] == 0 {
					n++
				}
			}
			if n <= laiZiCount {
				return true
			}
		}
		// 找 A 2 3 4 5
		n := 0
		if cardsCount[0] == 0 {
			n++
		}
		if cardsCount[1] == 0 {
			n++
		}
		if cardsCount[2] == 0 {
			n++
		}
		if cardsCount[3] == 0 {
			n++
		}
		if cardsCount[12] == 0 {
			n++
		}
		if n <= laiZiCount {
			return true
		}
	}
	return false
}

// 是不是同花
// 没有牌的用癞子填充
func isSameColor(cards []int) bool {
	color := -1
	for _, v := range cards {
		if v < 0 {
			continue
		}
		if color < 0 {
			color = ToColor(v)
		} else {
			if ToColor(v) != color {
				return false
			}
		}
	}
	return true
}

// ThreeColorFlush 找三同花顺
func ThreeColorFlush(cards [13]int, lai []int) bool {
	l := FindAllSameColorFlush(cards[:], lai)
	for _, v := range l {
		c1 := DelCards(cards[:], v)
		l1 := FindAllSameColorFlush(c1, lai)
		//fmt.Printf("第1层：%v--%v\n", PokersShow(v), PokersShow(c1))
		for _, vv := range l1 {
			//fmt.Printf("第2层：%v\n", PokersShow(vv))
			c2 := DelCards(c1, vv)
			//fmt.Printf("第3层：%v\n", PokersShow(c2))
			getLaiZiCards(c2, lai)
			if isFlush(c2) && isSameColor(c2) {
				return true
			}
		}
	}
	return false
}

// SameColor 找凑一色
// 13张牌都是黑色或红色
func SameColor(cards [13]int, lai []int) bool {
	getLaiZiCards(cards[:], lai)

	color := -1 // 黑色0 红色1
	for _, v := range cards {
		if v < 0 {
			continue
		}
		if ToColor(v) == 3 || ToColor(v) == 1 {
			color = 0
		} else {
			color = 1
		}
		break
	}
	if color < 0 {
		return false
	}

	for _, v := range cards {
		if v < 0 {
			continue
		}
		if ToColor(v) == 3 || ToColor(v) == 1 {
			if color == 1 {
				return false
			}
		} else {
			if color == 0 {
				return false
			}
		}
	}
	return true
}

// SixPairsHalf 找六对半
// 有六个对子就算
func SixPairsHalf(cards [13]int, lai []int) bool {
	_, cardsLaiZi, cardsCount := remainCards(cards[:], lai)
	n := 0
	for k, v := range cardsCount { // 找对子
		if v >= 2 {
			n += v / 2
			cardsCount[k] = v % 2
		}
	}
	p := 0
	for _, v := range cardsCount { // 找单张
		if v > 0 {
			p++
		}
	}
	ln := len(cardsLaiZi)
	if ln >= p {
		ln -= p
		n += p
		p = 0
	} else {
		n += ln
		p -= ln
		ln = 0
	}
	n += ln / 2
	if n == 6 {
		return true
	}
	return false
}

// ThreeContinuity 找三顺子
func ThreeContinuity(cards [13]int, lai []int) bool {
	l := FindAllFlush(cards[:], lai)
	for _, v := range l {
		c := DelCards(cards[:], v)
		l = FindAllFlush(c, lai)
		for _, vv := range l {
			c = DelCards(c, vv)
			getLaiZiCards(c, lai)
			if isFlush(c) {
				return true
			}
		}
	}
	return false
}

// ThreeColors 找三同花
func ThreeColors(cards [13]int, lai []int) bool {
	//sort.Sort(sort.Reverse(sort.IntSlice(cards[:])))
	getLaiZiCards(cards[:], lai)
	colorMap := make(map[int]int)
	for _, v := range cards {
		if v >= 0 {
			colorMap[ToColor(v)]++
		}
	}
	switch len(colorMap) {
	case 0:
		return false
	case 1:
		return false
	case 2:
		var c []int
		for _, v := range colorMap {
			c = append(c, v)
		}
		sort.Ints(c)
		if c[0] <= 3 && c[1] <= 10 {
			return true
		}
		if c[0] <= 5 && c[1] <= 8 {
			return true
		}

	case 3:
		var c []int
		for _, v := range colorMap {
			c = append(c, v)
		}
		sort.Ints(c)
		if c[0] <= 3 && c[1] <= 5 && c[2] <= 5 {
			return true
		}
	}
	return false
}

// 找五对三条
//func FivePairsThree(cards [13]int) bool {
//	valueMap := make(map[int]int)
//	for _, v := range cards {
//		valueMap[v%13]++
//	}
//	pairs := 0
//	three := 0
//	for _, v := range valueMap {
//		if v == 2 {
//			pairs++
//		} else if v == 3 {
//			three++
//		}
//	}
//	if pairs == 5 && three == 1 {
//		return true
//	}
//	return false
//}

// 找四套三条
//func FourThree(cards [13]int) bool {
//	valueMap := make(map[int]int)
//	for _, v := range cards {
//		valueMap[v%13]++
//	}
//	three := 0
//	for _, v := range valueMap {
//		if v == 3 {
//			three++
//		}
//	}
//	if three == 4 {
//		return true
//	}
//	return false
//}

// 找全小
//func AllSmall(cards [13]int) bool {
//	for _, v := range cards {
//		if v%13 > 6 {
//			return false
//		}
//	}
//	return true
//}

// 找全大
//func AllBig(cards [13]int) bool {
//	for _, v := range cards {
//		if v%13 < 6 {
//			return false
//		}
//	}
//	return true
//}

// 找三分天下
//func ThreeTheWorld(cards [13]int) bool {
//	fourMap := make(map[int]int)
//	for _, v := range cards {
//		fourMap[v%13]++
//	}
//	i := 0
//	for _, v := range fourMap {
//		if v == 4 {
//			i++
//		}
//	}
//	if i == 3 {
//		return true
//	}
//	return false
//}

// 找十二皇族
//func TwelveKing(cards [13]int) bool {
//	for _, v := range cards {
//		if v%13 < 9 {
//			return false
//		}
//	}
//	return true
//}

// GetSpecialType 找特殊牌型
// lai 癞子牌
func GetSpecialType(cards [13]int, lai []int) int {
	// 清龙判定
	if CyanLong(cards, lai) {
		return CyanLongType
	}
	// 找一条龙
	if ALong(cards, lai) {
		return ALongType
	}
	////找十二皇族
	//if TwelveKing(cards) {
	//	return TwelveKingType
	//}
	//找三同花顺
	if ThreeColorFlush(cards, lai) {
		return ThreeColorFlushType
	}
	////找三分天下
	//if ThreeTheWorld(cards) {
	//	return ThreeTheWorldType
	//}
	////找全大
	//if AllBig(cards) {
	//	return AllBigType
	//}
	////找全小
	//if AllSmall(cards) {
	//	return AllSmallType
	//}
	// 找凑一色
	if SameColor(cards, lai) {
		return SameColorType
	}
	////找四套三条
	//if FourThree(cards) {
	//	return FourThreeType
	//}
	////找五对三条
	//if FivePairsThree(cards) {
	//	return FivePairsThreeType
	//}

	// 找六对半
	if SixPairsHalf(cards, lai) {
		return SixPairsHalfType
	}

	// 找三顺子
	if ThreeContinuity(cards, lai) {
		return ThreeContinuityType
	}

	// 找三同花
	if ThreeColors(cards, lai) {
		return ThreeColorsType
	}
	return 0
}
