module AI
  where

import Types
import Util

mapFigure :: Figure -> (Int, Int) -> Field -> Field
mapFigure (block, r) (x, y) field = start
  where
    blockM = blockMatrix block
    blockL = length blockM
    figure = (apply r rotateCW) blockM

    start
        | y < 0     = loop (drop (-y) figure) field
        | otherwise = take y field ++ loop figure (drop y field)

    loop [] field' = field'
    loop _ []      = []
    loop figure' field'
        = line (head figure') (head field')
        : loop (tail figure') (tail field')

    line bline fline
        = take x fline
        ++ join bline (drop x fline)
        ++ drop (x + blockL) fline

    join [] _ = []
    join _ [] = []
    join (x : xs) (y : ys)
        | x == 1    = x : join xs ys
        | otherwise = y : join xs ys


hasContact :: Figure -> (Int, Int) -> Field -> Bool
hasContact figure (x, y) field
    = numSolid figure (x, y + 0) field
    > numSolid figure (x, y + 1) field
  where
    numSolid figure position
        = calcBlocks . paintField . mapFigure figure position


paintField :: Field -> Field
paintField = map (map (\x -> if x == 1 then 2 else x))


calcBlocks :: Field -> Int
calcBlocks = sum . concat . map (map (\x -> if x > 1 then 1 else 0))


dropFigure :: Figure -> (Int, Int) -> Field -> Field
dropFigure figure position@(x, y) field
    | hasContact figure position field
        = paintField $ mapFigure figure position field
    | otherwise
        = dropFigure figure (x, y + 1) field


fitness :: Field -> Int
fitness field = (sum . map calc . rotateCCW $ field)
  where
    width  = length field
    height = length (head field)
    calc = length . filter (< 2) . dropWhile (< 2)
