package api

import (
	"errors"
	"github.com/kataras/iris/v12"
	"github.com/sirupsen/logrus"
	"main/database"
	"main/model"
	"main/utils"
	"strconv"
	"strings"
)

// 初始化新棋盘
var cols = 15

func getRooms(ctx iris.Context) {
	db := database.GetInstance().GetMysqlDb()
	var rooms []typeRoomStatus
	if err := db.Model(&model.BackgammonRoom{}).Distinct("room_id").Order("room_id").Scan(&rooms).Error; err != nil {
		logrus.Errorln("sql执行失败：", err)
	}
	for k, v := range rooms {
		roomStatus, err := getRoomStatus(v.RoomId)
		if utils.ErrHandle(ctx, err) {
			return
		}
		rooms[k].Player = roomStatus.Player
	}
	err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", rooms))
	if utils.ErrHandle(ctx, err) {
		return
	}
}

// 删除房间
func delRoom(ctx iris.Context) {
	username := utils.GetLoginUser(ctx)
	if utils.DataIsNil(username) {
		return
	}
	id, err := strconv.Atoi(ctx.Params().Get("id"))
	if utils.ErrHandle(ctx, err) {
		return
	}
	roomStatus, err := getRoomStatus(id)
	if utils.ErrHandle(ctx, err) {
		return
	}
	db := database.GetInstance().GetMysqlDb()
	if roomStatus.Player == username.Username {
		if err1 := db.Where("room_id = ?", id).Delete(&model.BackgammonRoom{}).Error; err1 != nil {
			logrus.Errorln("sql执行失败：", err1)
		}
	} else if strings.Split(roomStatus.Player, ",")[0] == username.Username {
		if err1 := db.Create(&model.BackgammonRoom{
			RoomId:     roomStatus.RoomId,
			Player:     strings.Split(roomStatus.Player, ",")[1],
			Winner:     "",
			Current:    strings.Split(roomStatus.Player, ",")[1],
			PawnStatus: initPawns(),
		}).Error; err1 != nil {
			logrus.Errorln("sql执行失败：", err1)
		}
	} else if strings.Split(roomStatus.Player, ",")[1] == username.Username {
		if err1 := db.Create(&model.BackgammonRoom{
			RoomId:     roomStatus.RoomId,
			Player:     strings.Split(roomStatus.Player, ",")[0],
			Winner:     "",
			Current:    strings.Split(roomStatus.Player, ",")[0],
			PawnStatus: initPawns(),
		}).Error; err1 != nil {
			logrus.Errorln("sql执行失败：", err1)
		}
	}
	err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
	if utils.ErrHandle(ctx, err) {
		return
	}
}

func initPawns() string {
	var newPawns string
	for i := 0; i < cols; i++ {
		tmp := "0" + strings.Repeat(",0", cols-1)
		if i == 0 {
			newPawns = tmp
			continue
		}
		newPawns += ";" + tmp
	}
	return newPawns
}

// 新建房间
func addRoom(ctx iris.Context) {
	username := utils.GetLoginUser(ctx)
	if utils.DataIsNil(username) {
		return
	}
	var currentStatus model.BackgammonRoom
	db := database.GetInstance().GetMysqlDb()
	if err := db.Order("room_id desc").First(&currentStatus).Error; err != nil {
		logrus.Errorln("sql执行失败：", err)
	}
	newPawns := initPawns()
	if err := db.Create(&model.BackgammonRoom{
		RoomId:     currentStatus.RoomId + 1,
		Player:     username.Username,
		Current:    username.Username,
		Winner:     "",
		PawnStatus: newPawns,
	}).Error; err != nil {
		logrus.Errorln("sql执行失败：", err)
	}
	err := ctx.JSON(utils.FormatRes(iris.StatusOK, "", currentStatus.RoomId+1))
	if utils.ErrHandle(ctx, err) {
		return
	}
}

func joinRoom(ctx iris.Context) {
	username := utils.GetLoginUser(ctx)
	if utils.DataIsNil(username) {
		return
	}
	id, err := strconv.Atoi(ctx.Params().Get("id"))
	if utils.ErrHandle(ctx, err) {
		return
	}
	roomStatus, err := getRoomStatus(id)
	if utils.ErrHandle(ctx, err) {
		return
	}
	if utils.CheckListItem(strings.Split(roomStatus.Player, ","), username.Username) {
		ctx.StatusCode(iris.StatusBadRequest)
		ctx.SetErr(errors.New("无法重复加入房间"))
		return
	}
	if !utils.CheckListItem(strings.Split(roomStatus.Player, ","), username.Username) && len(strings.Split(roomStatus.Player, ",")) > 2 {
		ctx.StatusCode(iris.StatusBadRequest)
		ctx.SetErr(errors.New("房间人数已满"))
		return
	}
	roomStatus.Player = roomStatus.Player + "," + username.Username
	db := database.GetInstance().GetMysqlDb()
	if err1 := db.Model(&model.BackgammonRoom{}).Where("id = ?", roomStatus.ID).Updates(&roomStatus).Error; err1 != nil {
		logrus.Errorln("sql执行失败：", err1)
	}
	err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", "success"))
	if utils.ErrHandle(ctx, err) {
		return
	}
}

func getRoomStatus(roomId int) (model.BackgammonRoom, error) {
	var status model.BackgammonRoom
	db := database.GetInstance().GetMysqlDb()
	if err := db.Where("room_id = ?", roomId).Order("id desc").First(&status).Error; err != nil {
		logrus.Errorln("sql执行失败：", err)
	}
	if utils.DataIsNil(status) {
		return model.BackgammonRoom{}, errors.New("房间号不存在")
	}
	return status, nil
}

// 获取房间棋盘状态
func getStatus(ctx iris.Context) {
	id, err := strconv.Atoi(ctx.Params().Get("id"))
	if utils.ErrHandle(ctx, err) {
		return
	}
	roomStatus, err := getRoomStatus(id)
	if utils.ErrHandle(ctx, err) {
		return
	}
	err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", roomStatus))
	if utils.ErrHandle(ctx, err) {
		return
	}
}

// 新增棋子
func addPawn(ctx iris.Context) {
	username := utils.GetLoginUser(ctx)
	if utils.DataIsNil(username) {
		return
	}
	id, err := strconv.Atoi(ctx.Params().Get("id"))
	if utils.ErrHandle(ctx, err) {
		return
	}
	roomStatus, err := getRoomStatus(id)
	if utils.ErrHandle(ctx, err) {
		return
	}
	var tmpT string
	if roomStatus.Winner != "" {
		ctx.StatusCode(iris.StatusBadRequest)
		ctx.SetErr(errors.New("对局已结束"))
		return
	}
	if len(strings.Split(roomStatus.Player, ",")) != 2 {
		ctx.StatusCode(iris.StatusBadRequest)
		ctx.SetErr(errors.New("当前房间，玩家人数不足"))
		return
	}
	if roomStatus.Current != username.Username {
		ctx.StatusCode(iris.StatusBadRequest)
		ctx.SetErr(errors.New("现在不是你的回合"))
		return
	}
	if strings.Split(roomStatus.Player, ",")[0] == username.Username {
		tmpT = "1"
	} else if strings.Split(roomStatus.Player, ",")[1] == username.Username {
		tmpT = "-1"
	} else {
		ctx.StatusCode(iris.StatusBadRequest)
		ctx.SetErr(errors.New("非玩家，无法进行游戏"))
		return
	}
	place := strings.Split(ctx.URLParam("place"), ",")
	var newPawn []int
	for _, i := range place {
		tmp, _ := strconv.Atoi(i)
		newPawn = append(newPawn, tmp)
	}
	var pawnStatus [][]string
	for _, i := range strings.Split(roomStatus.PawnStatus, ";") {
		var tmp []string
		for _, j := range strings.Split(i, ",") {
			tmp = append(tmp, j)
		}
		pawnStatus = append(pawnStatus, tmp)
	}
	if pawnStatus[newPawn[0]][newPawn[1]] != "0" {
		ctx.StatusCode(iris.StatusBadRequest)
		ctx.SetErr(errors.New("该位置已有棋子"))
		return
	}
	winner := getWinner(pawnStatus, tmpT, [2]int{newPawn[0], newPawn[1]})
	if winner {
		roomStatus.Winner = username.Username
	}
	pawnStatus[newPawn[0]][newPawn[1]] = tmpT
	var tmp []string
	for _, i := range pawnStatus {
		tmp = append(tmp, strings.Join(i, ","))
	}
	roomStatus.PawnStatus = strings.Join(tmp, ";")
	roomStatus.Current = strings.Replace(strings.Replace(roomStatus.Player, username.Username, "", 1), ",", "", 1)
	db := database.GetInstance().GetMysqlDb()
	if err1 := db.Create(&model.BackgammonRoom{
		RoomId:     roomStatus.RoomId,
		Player:     roomStatus.Player,
		Winner:     roomStatus.Winner,
		Current:    roomStatus.Current,
		PawnStatus: roomStatus.PawnStatus,
	}).Error; err1 != nil {
		logrus.Errorln("sql执行失败：", err1)
	}
	err = ctx.JSON(utils.FormatRes(iris.StatusOK, "", roomStatus))
	if utils.ErrHandle(ctx, err) {
		return
	}
}

// 判断当前是否存在winner
func getWinner(pawns [][]string, t string, pawn [2]int) bool {
	pawnAround := [8][2]int{{pawn[0] - 1, pawn[1] - 1}, {pawn[0], pawn[1] - 1}, {pawn[0] + 1, pawn[1] - 1}, {pawn[0] - 1, pawn[1]},
		{pawn[0] + 1, pawn[1]}, {pawn[0] - 1, pawn[1] + 1}, {pawn[0], pawn[1] + 1}, {pawn[0] + 1, pawn[1] + 1}}
	around := [8]int{0, 0, 0, 0, 0, 0, 0, 0}
	for i, p := range pawnAround {
		if p[0] >= 0 && p[1] >= 0 && p[0] < cols && p[1] < cols && pawns[p[0]][p[1]] == t {
			current := [2]int{p[0], p[1]}
			for j := 0; j < 3; j++ {
				switch i {
				case 0:
					current[0]--
					current[1]--
				case 1:
					current[1]--
				case 2:
					current[0]++
					current[1]--
				case 3:
					current[0]--
				case 4:
					current[0]++
				case 5:
					current[0]--
					current[1]++
				case 6:
					current[1]++
				case 7:
					current[0]++
					current[1]++
				}
				//fmt.Println(current)
				if current[0] < 0 || current[0] > cols-1 || current[1] < 0 || current[1] > cols-1 || pawns[current[0]][current[1]] != t {
					around[i] = j + 1
					break
				}
				around[i] = j + 2
			}
		}
	}
	if around[0]+around[7] >= 4 || around[1]+around[6] >= 4 || around[2]+around[5] >= 4 || around[3]+around[4] >= 4 {
		return true
	}
	return false
}
