/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import mediaQuery from '@ohos.mediaquery'
import chessNapi from "libchess.so"
import prompt from '@ohos.prompt';
import Logger from '../model/Logger'

const AI_CHESS: number = 2 // 2为AI落子
const USER_CHESS: number = 1 // 1为用户落子
const AI_WIN: number = 2 // 2代表AI胜利
const USER_WIN: number = 1 // 1代表用户胜利
const SIZE: number = 15
const TAG: string = 'Index'

function initArray(size, value) {
  return Array.from({ length: size }, () => Array.from({ length: size }, () => value))
}

@Entry
@Component
struct Index {
  private listener = mediaQuery.matchMediaSync('screen and (min-aspect-ratio: 1.5) or (orientation: landscape)')
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  @State chessboard: Array<Array<number>> = initArray(SIZE, 0)
  @State message: Resource = $r('app.string.game_not_start')
  @State @Watch('isPlayChange') isPlay: boolean = false
  @State isLand: boolean = false
  onLand = (mediaQueryResult) => {
    console.info(`[eTSMediaQuery.Index]onLand: mediaQueryResult.matches=${mediaQueryResult.matches}`)
    this.isLand = mediaQueryResult.matches
  }

  getChessImg(item) {
    if (item === USER_CHESS) {
      return $r('app.media.ic_white')
    }
    if (item === AI_CHESS) {
      return $r('app.media.ic_black')
    }
    return undefined
  }

  isPlayChange() {
    Logger.info(TAG, `isPlayChange,isPlay:${this.isPlay}, message:${this.message}`)
    if (!this.isPlay) {
      AlertDialog.show({
        message: this.message,
        primaryButton: {
          value: $r('app.string.sure'),
          action: () => {
            this.chessboard = initArray(SIZE, 0)
            this.drawBoard()
          }
        }
      })
    }
  }

  aiPlay() {
    Logger.info(TAG, 'aiPlay')
    if (this.message === $r('app.string.wait')) {
      return
    }
    chessNapi.deal((data: string) => {
      let result = data.split(',')
      let succeed = parseInt(result[0], 10)
      let x = parseInt(result[1], 10)
      let y = parseInt(result[2], 10)
      Logger.info(TAG, `succeed:${succeed},x:${x},y:${y}`)
      this.chessboard[x][y] = AI_CHESS
      this.drawChess([x, y], AI_CHESS)
      if (succeed === AI_WIN) {
        this.message = $r('app.string.ai_win')
        this.isPlay = false
        return
      }
      if (x > SIZE && y > SIZE) {
        this.message = $r('app.string.game_over')
        this.isPlay = false
        return
      }
      this.message = $r('app.string.ai_landed')
    })
  }

  drawBoard() {
    this.context.clearRect(0, 0, this.context.width, this.context.height)
    this.chessboard.forEach((xItem, x) => {
      xItem.forEach((yItem, y) => {
        this.drawChess([x, y], yItem)
      })
    })
  }

  drawChess(position: [x: number, y: number], chess: number) {
    this.context.lineWidth = 2
    if (chess === AI_CHESS) {
      this.context.fillStyle = '#000'
      this.context.strokeStyle = '#000'
    } else if (chess === USER_CHESS) {
      this.context.fillStyle = '#fdfdfd'
      this.context.strokeStyle = '#f0f0f0'
    } else {
      return
    }
    let gridSize = this.context.width / (SIZE + 1)
    let x = gridSize * (position[0] + 1)
    let y = gridSize * (position[1] + 1)
    Logger.info(TAG, `drawChess, x=${x},y=${y}`)
    this.context.save()
    this.context.beginPath()
    this.context.translate(x, y)
    this.context.arc(0, 0, px2vp(18), 0, 2 * Math.PI, false)
    this.context.fill()
    this.context.stroke()
    this.context.restore()
  }

  putChess = (event: ClickEvent) => {
    if (!this.isPlay) {
      prompt.showToast({ message: '请先点击开始游戏' })
      return
    }
    let gridSize = this.context.width / SIZE
    let dx = Math.floor(event.x / gridSize)
    let dy = Math.floor(event.y / gridSize)
    console.info(`putChess dx=${dx},dy=${dy}`)
    if (this.chessboard[dx][dy] > 0 || dy >= SIZE || dx >= SIZE) {
      return
    }
    this.chessboard[dx][dy] = USER_CHESS
    this.drawChess([dx, dy], USER_CHESS)
    this.message = $r('app.string.wait')
    let succeed = chessNapi.put(dx, dy)
    Logger.info(TAG, `put, succeed=${succeed}`)
    if (succeed === USER_WIN) {
      this.message = $r('app.string.you_win')
      this.isPlay = false
    } else {
      this.aiPlay()
    }
  }

  aboutToAppear() {
    this.listener.on('change', this.onLand)
  }

  build() {
    Column() {
      Row() {
        Text($r('app.string.MainAbility_label'))
          .fontColor(Color.White)
          .fontSize(28)
      }
      .width('100%')
      .height('8%')
      .constraintSize({ minHeight: 70 })
      .padding({ left: 10, right: 10 })
      .backgroundColor('#0D9FFB')

      if (this.isLand) {
        Canvas(this.context)
          .height('70%')
          .aspectRatio(1)
          .backgroundImage($r('app.media.ic_bg'))
          .backgroundImageSize({ width: '100%', height: '100%' })
          .onReady(() => {
            this.drawBoard()
          })
          .onClick(this.putChess)
      } else {
        Canvas(this.context)
          .width('95%')
          .aspectRatio(1)
          .backgroundImage($r('app.media.ic_bg'))
          .backgroundImageSize({ width: '100%', height: '100%' })
          .onReady(() => {
            this.drawBoard()
          })
          .onClick(this.putChess)
      }

      if (!this.isPlay) {
        Button({ type: ButtonType.Capsule }) {
          Text($r('app.string.game_start'))
            .fontSize(25)
            .fontColor(Color.White)
        }
        .width('80%')
        .height(50)
        .margin(10)
        .onClick(() => {
          if (this.isPlay) {
            prompt.showToast({ message: '游戏已开始' })
            return
          }
          this.isPlay = true
          this.aiPlay()
        })
      }

      Text(this.message)
        .fontSize(25)
        .fontColor(Color.Black)
        .margin(10)
    }
    .width('100%')
    .height('100%')
  }
}