# -*- coding: utf_8 -*-
# author www.chedanji.com

from xml.etree import ElementTree as etree
from xml.etree.ElementTree import Element, SubElement, ElementTree
import subprocess
from xml.dom import minidom
import os
import time
import io
import json
import getopt
import datetime
import urllib2
import re

alfred_workflow_data = os.environ['alfred_workflow_data']
repo_directory = alfred_workflow_data + '/tldr'
default_platform = 'osx'

def query(query):
  global default_platform
  clone()

  dic = parse_args(query)
  isUpdate = dic['isUpdate']
  default_platform = dic['platform']
  command = dic['command']

  if bool(isUpdate):
    update()
    output_title('Update success')
  else:
    update(7)

  if(len(query) == 0):
    rowList = [{
      'uid': '1',
      'arg': '',
      'autocomplete': '',
      'icon': 'icon.png',
      'title': 'Please input',
      'valid': 'no'
    }]
  else:
    # output_title(command)
    rowList = parse_man_page(command)
    if(len(rowList) == 0):
      rowList = hint(command, default_platform)
    if(len(rowList) == 0):
      rowList = [{
        'uid': '1',
        'arg': '',
        'autocomplete': '',
        'icon': 'icon.png',
        'title': 'Page not found',
        'valid': 'no'
      }]
  print gen_xml(rowList)

def find_page_location(command):

  with io.open(os.path.join(alfred_workflow_data, 'index.json'),
               encoding='utf-8') as f:
    index = json.load(f)
  command_list = [item['name'] for item in index['commands']]
  if command not in command_list:
    return os.path.join(os.path.join(repo_directory, 'pages'),
                    os.path.join("common", command + '.md'))

  supported_platforms = index['commands'][
    command_list.index(command)]['platform']
  if default_platform in supported_platforms:
    platform = default_platform
  elif 'common' in supported_platforms:
    platform = 'common'
  else:
    platform = ''

  if not platform:
    return
  page_path = os.path.join(os.path.join(repo_directory, 'pages'),
                        os.path.join(platform, command + '.md'))
  return page_path

def parse_page(page):
  with io.open(page, encoding='utf-8') as f:
    lines = f.readlines()

  if (len(lines) <= 0):
    return []

  first_line = lines[0]
  if (first_line.startswith('#')):
    return parse_old_page(lines)
  else:
    return parse_new_page(lines)

def parse_old_page(lines):
  row_list = []
  uid = 1
  item = {}
  description = {}
  for line in lines:
    if line.startswith('#'):
      continue
    elif line.startswith('-'):
      item = {}
      item['uid'] = str(uid)
      item['subtitle'] = line.replace('-', '').replace(':', '').strip()
    elif line.startswith('`'):
      item['title'] = line.replace('`', '').replace('{{', '').replace('}}', '').strip()
      row_list.append(item)

    uid += 1
  return row_list

def parse_new_page(lines):
  row_list = []
  uid = 1
  item = {}
  code_pattern = re.compile(r'^( {4,} | \t)')
  subtext_pattern = re.compile(r'^\=?$')
  for line in lines:
    if (len(line.strip() == 0)):
      continue
    elif (code_pattern.match(line)):
      item[title] = line.replace('{{', '').replace('}}', '').strip()
      row_list.append(item)
    elif (subtext_pattern.match(line.rstrip())):
      continue
    else:
      item = {}
      item['uid'] = str(uid)
      item[subtitle] = line.strip()

    uid += 1

  return row_list

def parse_man_page(command):
  page_path = find_page_location(command)
  if page_path and os.path.exists(page_path):
    return parse_page(page_path)

  return []

def gen_xml(rowList):
  items = Element('items')

  for row in rowList:
    item = SubElement(items, 'item')
    item.set('autocomplete', row.get('autocomplete') or '')
    item.set('uid', row.get('uid') or '')
    item.set('arg', row.get('title') or '')
    item.set('valid', row.get('valid') or '')

    title = SubElement(item, 'title')
    title.text = row.get('title') or ''

    subtitle = SubElement(item, 'subtitle')
    subtitle.text = row.get('subtitle') or ''

    icon = SubElement(item, 'icon')
    icon.text = row.get('icon')

  tree = minidom.parseString(etree.tostring(items))
  return tree.toxml()

def output_title(msg):
  print gen_xml([{
        'uid': str(time.time()),
        'arg': '',
        'autocomplete': '',
        'icon': 'icon.png',
        'title': str(msg),
        'valid': 'no'
      }])

def clone():
  if(not os.path.exists(alfred_workflow_data)):
    os.mkdir(alfred_workflow_data)

  if(not os.path.exists(repo_directory)):
    child = subprocess.Popen(['git clone https://github.com/tldr-pages/tldr.git ' + '"' + str(repo_directory) + '"'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    success, err = child.communicate()
    if child.returncode:
      raise Exception(err)
    download_index()

def update(days=0):
  if days > 0 and os.path.exists(os.path.join(alfred_workflow_data, 'config.json')):
    with io.open(os.path.join(alfred_workflow_data, 'config.json'),
        encoding='utf-8') as f:
      try:
        config = json.load(f)
      except:
        config = {'update_date': datetime.datetime.now().strftime('%Y%m%d')}

    if (datetime.datetime.now().date() - datetime.datetime.strptime(config['update_date'], '%Y%m%d').date()).days < days:
      return
  os.chdir(repo_directory)
  local = subprocess.check_output('git rev-parse master'.split()).strip()
  remote = subprocess.check_output(
    'git ls-remote https://github.com/tldr-pages/tldr/ HEAD'.split()
  ).split()[0]

  if local != remote:
    subprocess.check_call('git checkout master'.split())
    subprocess.check_call('git pull --rebase'.split())

  with io.open(os.path.join(alfred_workflow_data, 'config.json'), mode='wb') as f:
    data = {
      'update_date': datetime.datetime.now().strftime('%Y%m%d')
    }
    json.dump(data, f)
    download_index()


def parse_args(query=''):
  query = query.split()
  dic = {
    'isUpdate': False,
    'platform': default_platform,
    'command': ''
  }
  try:
    opts, args = getopt.gnu_getopt(query, 'uo:')
  except:
    return dic

  for opt, arg in opts:
    if opt == '-u':
      dic['isUpdate'] = True
    elif opt == '-o':
      dic['platform'] = arg

  dic['command'] = '-'.join(args)

  return dic


def download_index():
  url = 'http://tldr.sh/assets/index.json'
  req = urllib2.Request(url, headers={'User-Agent' : "Magic Browser"})
  try:
    res = urllib2.urlopen(req)
  except urllib2.HTTPError,e:
    print(e)
    return
  with io.open(os.path.join(alfred_workflow_data, 'index.json'), mode='wb') as f:
    f.write(res.read())

def hint(command, platform=''):
  if (len(command) == 0):
    return []

  with io.open(os.path.join(alfred_workflow_data, 'index.json'),
               encoding='utf-8') as f:
    index = json.load(f)

  result = []
  for item in index['commands']:
    if (platform in item['platform'] or 'common' in item['platform']) and command == item['name'][0: len(command)]:
      if platform == 'osx':
        autocomplete = item['name']
      elif len(platform) > 0:
        autocomplete = item['name'] + ' -o ' + platform

      result.append({
        'uid': str(time.time()),
        'arg': '',
        'autocomplete': autocomplete,
        'icon': 'icon.png',
        'title': item['name'],
        'valid': 'no'
      })
  return result