local gc=love.graphics
local floor=math.floor

local lines={
    {1,2,3},
    {4,5,6},
    {7,8,9},
    {1,4,7},
    {2,5,8},
    {3,6,9},
    {1,5,9},
    {3,5,7},
}

local board={{},{},{},{},{},{},{},{},{}}
local score={}

local lastX,lastx
local curX,curx
local round
local target
local placeTime
local gameover

local function restart()
    lastX,lastx=false,false
    curX,curx=nil
    round=0
    target=false
    placeTime=TIME()
    gameover=false
    for X=1,9 do
        score[X]=false
        for x=1,9 do
            board[X][x]=false
        end
    end
end
local function checkBoard(b,p)
    for i=1,8 do
        local testNextLine
        for j=1,3 do
            if b[lines[i][j]]~=p then
                testNextLine=true
                break-- goto CONTINUE_testNextLine
            end
        end
        if not testNextLine then return true end
        -- ::CONTINUE_testNextLine::
    end
end
local function full(L)
    for i=1,9 do
        if not L[i] then
            return false
        end
    end
    return true
end
local function place(X,x)
    board[X][x]=round
    SFX.play('touch')
    lastX,lastx=X,x
    curX,curx=nil
    placeTime=TIME()
    if checkBoard(board[X],round) then
        score[X]=round
        if checkBoard(score,round) then
            gameover=round
            SFX.play('win')
            return
        else
            if full(score) then
                gameover=true
                return
            end
        end
        SFX.play('reach')
    else
        if full(board[X]) then
            SFX.play('emit')
            score[X]=true
            if full(score) then
                gameover=true
                return
            end
        end
    end
    if score[x] then
        target=false
    else
        target=x
    end
    round=1-round
end

local scene={}

function scene.enter()
    restart()
    BGM.play('truth')
    BG.set('rainbow')
    DiscordRPC.update("Playing Ultimate Tic-Tac-Toe")
end

function scene.mouseMove(x,y)
    x,y=floor((x-280)/80),floor(y/80)
    curX,curx=floor(x/3)+floor(y/3)*3+1,x%3+y%3*3+1
    if
        x<0 or x>8 or
        y<0 or y>8 or
        curX<1 or curX>9 or
        curx<1 or curx>9 or
        score[curX] or
        not (target==curX or not target) or
        board[curX][curx] or
        gameover
    then
        curX,curx=nil
    end
end

function scene.mouseDown(x,y)
    scene.mouseMove(x,y)
    if curX then
        place(curX,curx)
    end
end

scene.touchDown=scene.mouseMove
scene.touchMove=scene.mouseMove
scene.touchUp=scene.mouseDown

function scene.draw()
    gc.push('transform')
    -- origin pos:0,140; scale:4
    gc.translate(280,0)
    gc.scale(8)

    -- Draw board
    gc.setColor(COLOR.dX)
    gc.rectangle('fill',0,0,90,90)

    -- Draw target area
    gc.setColor(1,1,1,math.sin((TIME()-placeTime)*5)*.1+.15)
    if target then
        gc.rectangle('fill',(target-1)%3*30,floor((target-1)/3)*30,30,30)
    elseif not gameover then
        gc.rectangle('fill',0,0,90,90)
    end

    -- Draw cursor
    if curX then
        gc.setColor(1,1,1,.3)
        gc.rectangle('fill',(curX-1)%3*30+(curx-1)%3*10-.5,floor((curX-1)/3)*30+floor((curx-1)/3)*10-.5,11,11)
    end

    gc.setLineWidth(.8)
    for X=1,9 do
        if score[X] then
            if score[X]==0 then
                gc.setColor(.5,0,0)
            elseif score[X]==1 then
                gc.setColor(0,0,.5)
            else
                gc.setColor(COLOR.D)
            end
            gc.rectangle('fill',(X-1)%3*30,floor((X-1)/3)*30,30,30)
        end
        for x=1,9 do
            local c=board[X][x]
            if c then
                local _x=(X-1)%3*30+(x-1)%3*10
                local _y=floor((X-1)/3)*30+floor((x-1)/3)*10
                if c==0 then
                    gc.setColor(1,.2,.2)
                    gc.rectangle('line',_x+2.25,_y+2.25,5.5,5.5)
                else
                    gc.setColor(.3,.3,1)
                    gc.line(_x+2,_y+2,_x+8,_y+8)
                    gc.line(_x+2,_y+8,_x+8,_y+2)
                end
            end
        end
    end

    -- Draw board line
    gc.setLineWidth(.8)
    for x=0,9 do
        gc.setColor(1,1,1,x%3==0 and 1 or .3)
        gc.line(10*x,0,10*x,90)
        gc.line(0,10*x,90,10*x)
    end

    -- Draw last pos
    if lastX then
        gc.setColor(.5,1,.4,.8)
        local r=.5+.5*math.sin(TIME()*6.26)
        gc.rectangle('line',(lastX-1)%3*30+(lastx-1)%3*10-r,floor((lastX-1)/3)*30+floor((lastx-1)/3)*10-r,10+2*r,10+2*r)
    end
    gc.pop()

    if gameover then
        -- Draw result
        FONT.set(60)
        if gameover==0 then
            gc.setColor(1,.6,.6)
            GC.mStr("RED\nWON",1140,200)
        elseif gameover==1 then
            gc.setColor(.6,.6,1)
            GC.mStr("BLUE\nWON",1140,200)
        else
            gc.setColor(.8,.8,.8)
            GC.mStr("TIE",1140,240)
        end
    else
        -- Draw current round mark
        gc.setColor(COLOR.X)
        gc.rectangle('fill',80,80,160,160)
        gc.setColor(COLOR.Z)
        gc.setLineWidth(6)
        gc.rectangle('line',80,80,160,160)

        gc.setLineWidth(10)
        if round==0 then
            gc.setColor(1,0,0)
            gc.rectangle('line',160-40,160-40,80,80)
        else
            gc.setColor(0,0,1)
            gc.line(160-45,160-45,160+45,160+45)
            gc.line(160-45,160+45,160+45,160-45)
        end
    end
end

scene.widgetList={
    WIDGET.newButton{name='reset',x=1140,y=540,w=170,h=80,font=50,fText=CHAR.icon.retry_spin,color='lG',code=restart},
    WIDGET.newButton{name='back',x=1140,y=640,w=170,h=80,sound='back',font=60,fText=CHAR.icon.back,code=backScene},
}

return scene
