# AUTHOR: Kale Miller
# DESCRIPTION: Front end execution of the chess engine.

# 416c7761797320636f646520617320696620746865206775792077686f20656e6473207570206d
# 61696e7461696e696e6720796f757220636f64652077696c6c20626520612076696f6c656e7420
# 70737963686f706174682077686f206b6e6f777320776865726520796f75206c6976652e

# DEVELOPMENT LOG:
#    30/12/16: Initalised the front-end script. Added psuedo code.

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~EXECUTION~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"""
DRAFT EXECUTION - DEBUGGING LEVEL OF UI:
===================
- Start up program.
- Prompt the user to set up the board. This is done by passing in the pieces (
which would be symbolised by their notation like K for king, N for knight) with
a set of coordinates.
- Otherwise let a default game be generated.

- ???
- Profit.
"""
import time, sys, random
from lib import core, chessboard, engine, movegenerator, pieces, usercontrol

# Define globals.
if len(sys.argv) > 1:
    script, debug = sys.argv
else:
    debug = False

VERSION = 'alpha 1.00.00'
if debug: SLEEP_TIME = 0.01
else: SLEEP_TIME = 1
USER_OPTIONS = ['hist', 'move', 'exit']
HELPMESSAGE_NOTATION = """
Each move is written in the following format:
    Symbol + position + movetype + position

 - The symbol that starts the notation is the piece's symbol. This is similar to
   traditional notation with K, Q, B, N, R and P representing the king, queen,
   bishop, knight, rook and pawn respectively.
 - Next is the start position, which is file then rank. For example, e5.
 - To connect the start and end position either '>' is used if there is a move
   or a 'x' if there is a capture.
 - The last part is the final position, which is again file then rank.

There is only two special formats which you need to be concerned with other then
these basic moves. If you want to castle kingside use 0-0 and if if you wish to
castle queenside use 0-0-0.
"""

# Initialise the components of the board.
UI = usercontrol.EngineUI()
GUI = usercontrol.EngineGUI()

def rest():
    """Pauses a program for the designated time."""
    time.sleep(SLEEP_TIME)
    return None

def startprogram():
    print "Welcome, to Quark Chess Engine!"
    print "You are playing the version %r of the engine.\n\n" % VERSION
    rest()
    print "Let me introduce you to the rules."
    rest()
    print " - The board is rendered as an ASCII picture. Each piece has its "
    print "   own symbol (K, Q, B, N, R and P) which is either capitalised if "
    print "   white or lowercase if black. If the square is blank then a period "
    print "   (the '.' symbol) is used to denote the square."""
    rest(); rest(); rest()
    print " - To make a move you are required to pass a notation string to\n" \
          "   designate where you wish to move to. This notation string however\n" \
          "   is special as it helps to clearly define what move you wish to\n" \
          "   make.\n"
    rest(); rest(); rest()
    print "PRESS ENTER TO CONTINUE."
    raw_input()
    return None


def letuserpickgametype():
    """Lets the user pick what board/gametype they want to play on."""
    print "During this alpha you can only play on a normal chess board."
    rest()
    print "Initalising the chessboard..."
    board = chessboard.ChessBoard
    print "Done!"
    return board


def initialisethisboard(boardtype):
    """Creates the board to play on. Just calls the class to initalise it."""
    board = boardtype()
    # board[53] = pieces.PawnPiece('white')
    #
    # board[56] = pieces.KingPiece('black')
    # board[45] = pieces.KingPiece('white')
    board.setupnormalboard()
    return board


def whogoesfirst():
    """Determines if the player or computer goes first."""
    return True  # HACK: Until I write proper code.


def promptuser(commandlist):
    """Get the user's command."""
    # commanddict = {
    #     'hist': printmovehistory,
    #     'move': processmove,
    #     'quit': resign
    # }
    print "What would you like to do? Please pass what is in the parenthesis."
    print "  - Get the move history (%s)" % commandlist[0]
    print "  - Make a move (%s)" % commandlist [1]
    print "  - Resign (%s)" % commandlist[2]

    while True:
        usercommand = raw_input('> ')
        if usercommand in commandlist:
            return usercommand
        else:
            print "Not a valid option. Please pass one of %s" % commandlist
    return None


def promptuserformove():
    """Get the move that the user wants to make."""
    print "\nPlease type in the move string you wish to make. If you want to see"
    print "the rules for making these special strings type 'help'."
    while True:
        movestring = raw_input('> ')
        try:
            if movestring.lower() == 'help':
                print HELPMESSAGE_NOTATION
                continue
            else:
                piecetomove, movetuple = UI.processusermove(movestring)
        except (NameError, core.UnknownPieceError) as e:
            print "%r is not a valid string." % movestring
            print "Type 'help' if you need assistance with the naming rules."
        else:
            break
    return piecetomove, movetuple, movestring


def promptuserforpawnpromotion():
    """Gets the piece the pawn will be promoted to."""
    print ("\nWhat would you like to promote the pawn too? Use the notation "
           "symbol, not the full name of the piece (Q, N, B, R).")
    while True:
        promotepiece = raw_input('> ')
        if promotepiece not in ('Q', 'N', 'B', 'R'):
            print "Not a valid piece. It must be any of (Q, N, B, R)."
        else:
            if promotepiece == 'Q': return pieces.QueenPiece
            elif promotepiece == 'B': return pieces.BishopPiece
            elif promotepiece == 'N': return pieces.KnightPiece
            elif promotepiece == 'R': return pieces.RookPiece
    return None


def islegalmove(colour, movetuple, board):
    """Determine if the move is legal."""
    generator = movegenerator.MoveGenerator(board)
    allallowedmoves = generator.generatemovelist(colour)
    return movetuple in allallowedmoves


def pawnpromotion(movetuple, colour):
    """Determines if the move was a promotion move."""
    finalcoord = core.convert(movetuple[1], tocoordinate=True)
    finalrank = finalcoord[0]