#!/usr/bin/python3
# -*- coding: utf-8 -*-

import argparse
import sys
from urllib.parse import quote, unquote, urlparse, parse_qs


url = 'http://www.eddins.net/steve/chess/ChessImager/ChessImager.php'
default_ds_color = '1793D1'
default_ls_color = 'FCFDFE'
default_fen= 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR'

data_types = {
  'fen' : 'Forsyth–Edwards notation',
  'url' : 'A URL to Steve Eddins\' Chess Imager (http://www.eddins.net/steve/chess/chessimager)',
  'unicode' : 'A board representation using Unicode chess symbols (0x2654-0x265f)',
}

input_source = [
  'cli',
  'stdin',
  'file'
]

char2piece = {
  'p' : '♟',
  'r' : '♜',
  'n' : '♞',
  'b' : '♝',
  'q' : '♛',
  'k' : '♚',
  'P' : '♙',
  'R' : '♖',
  'N' : '♘',
  'B' : '♗',
  'Q' : '♕',
  'K' : '♔'
}

piece2char = {}
for c,p in char2piece.items():
 piece2char[p] = c


piece_styles = [
  'adventurer',
  'alfonso',
  'cases',
  'condal',
  'harlequin',
  'kingdom',
  'leipzig',
  'line',
  'lucena',
  'magnetic',
  'mark',
  'marroquin',
  'maya',
  'mediaeval',
  'merida',
  'motif'
]



def hex2rgb(c):
  c = c.lstrip('#')
  #rgb = map(lambda x: int(x,16), (color[0:2], color[2:4], color[4:6]))
  #return "({0},{1},{2})".format(*rgb)
  c = int(c, 16)
  return "(%d,%d,%d)" % ((c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff)


def fen2unicode(fen=default_fen):
  board = ''
  for i in range(1,9):
    fen = fen.replace(str(i), ' ' * i)
  for c in fen:
    if c == '/':
      board += '\n'
    elif c == ' ':
      board += c
    else:
      board += char2piece[c]
  return board


def unicode2fen(board=None):
  if not board:
    return default_fen
  col = 0
  fen = ''
  for c in board:
    if c == '\n':
      if col < 8:
        fen += str(8-col)
      fen += '/'
      col = 0
    elif c == ' ':
      fen += c
      col += 1
    else:
      fen += piece2char[c]
      col += 1

  for i in range(8,0,-1):
    s = ' ' * i
    fen = fen.replace(s,str(i))

  return fen



def create_uri(
  fen=default_fen,
  ls_color=default_ls_color,
  ds_color=default_ds_color,
  piece_style=piece_styles[-2],
  reverse=False,
  coordinates=False,
  border_color=None,
  border_width=None,
  square_size=None
):
  uri = "%s?fen=%s&ls_color=%s&ds_color=%s&piece_style=%s" % (
    url,
    fen,
    quote(hex2rgb(ls_color)),
    quote(hex2rgb(ds_color)),
    piece_style
  )

  if reverse:
    uri += '&direction=reverse'
  if coordinates:
    uri += '&coordinates=on'
  if border_color:
    uri += '&border_color=%s' % (quote(hex2rgb(border_color)))
  if border_width:
    uri += '&border_width=%d' % (border_width)
  if square_size:
    uri += '&square_size=%d' % (square_size)

  return uri


if __name__ == '__main__':

  data_types_help = ''
  for dt in sorted(data_types.keys()):
    data_types_help += " %s: %s." % (dt, data_types[dt])

  parser = argparse.ArgumentParser()

  parser.add_argument('input', metavar='<data>', action='store', nargs='?',
                      help='the input data - see "--input-type"')

  parser.add_argument('--border-color', dest='border_color', action='store',
                      metavar='xxyyzz',
                      help='set border color')

  parser.add_argument('--border-width', dest='border_width', action='store',
                      type=int,
                      help='set border width')

  parser.add_argument('--coordinates', dest='coordinates', action='store_true',
                      help='show coordinates')

  parser.add_argument('--ds-color', dest='ds_color', action='store',
                      metavar='xxyyzz', default=default_ds_color,
                      help='dark square color')

  parser.add_argument('--ls-color', dest='ls_color', action='store',
                      metavar='xxyyzz', default=default_ls_color,
                      help='light square color')

  parser.add_argument('--input-type', dest='input_type', action='store',
                      choices=data_types, default='fen',
                      help='input data type - %s' % data_types_help)

  parser.add_argument('--output-type', dest='output_type', action='store',
                      choices=data_types, default='url',
                      help='output data type - %s' % data_types_help)

  parser.add_argument('--input-source', dest='input_source', action='store',
                      choices=input_source, default=input_source[0],
                      help='input data source')

  parser.add_argument('--piece-style', dest='piece_style', action='store',
                      choices=piece_styles, default=piece_styles[-2],
                      help='piece style')

  parser.add_argument('--reverse', dest='reverse', action='store_true',
                      help='reverse the board')

  parser.add_argument('--square-size', dest='square_size', action='store',
                      type=int,
                      help='set square size')

  args = parser.parse_args()



  data = None
  if args.input_source == 'cli':
    data = args.input
  elif args.input_source == 'stdin':
    data = sys.stdin.read()
  elif args.input_source == 'file':
    with open(args.input) as f:
      data = f.read()

  if not data:
    data = default_fen
    args.input_type = 'fen'

  if args.input_type == 'url':
    url = urlparse(data)
    query = url.query
    qs = parse_qs(query)
    try:
      data = qs['fen'][0]
    except KeyError:
      data = default_fen
    args.input_type = 'fen'

  elif args.input_type == 'unicode':
    data = unicode2fen(data)
    args.input_type = 'fen'


  if args.output_type == args.input_type \
  or args.output_type == 'fen':
    print(data)
    sys.exit()

  elif args.output_type == 'unicode':
    data = fen2unicode(data)
    print(data)
    sys.exit()

  elif args.output_type == 'url':
    data = create_uri(
      fen=data,
      ls_color=args.ls_color,
      ds_color=args.ds_color,
      piece_style=args.piece_style,
      reverse=args.reverse,
      coordinates=args.coordinates,
      border_color=args.border_color,
      border_width=args.border_width,
      square_size=args.square_size
    )
    print(data)
    sys.exit()

  else:
    sys.stderr.write('error: something went horribly wrong and it\'s all your fault')
    sys.exit(1)









