#!/usr/bin/env python

import os
import re
import sys
import argparse
import subprocess

SEP = '\r\n'
VERSION = '0.0.5'

def response(ver, body):
    sys.stdout.write('%s 200 OK\r\n' % ver)
    headers = [('Access-Control-Allow-Origin', '*'), ('Content-Length', str(len(body)))]
    sys.stdout.write(''.join([k+': ' + v + SEP for k, v in headers]))
    sys.stdout.write(SEP)
    sys.stdout.write(body)
    sys.stdout.flush()

def get_active_mac(group):
    if group[-1].strip() != 'status: active':
        return
    mac = ip = None
    for line in group:
        line = line.strip().split(' ')
        if not line:
            continue
        if line[0] == 'ether':
            mac = line[1]
        if line[0] == 'inet':
            ip = line[1]
    if mac and ip:
        return mac + ',' + ip

def getmac():
    # networksetup -listallhardwareports | grep "Ethernet Address"
    output = subprocess.check_output('ifconfig', shell=True)
    lines = output.split('\n')
    groups = []
    group = None
    for line in lines:
        if line.startswith('\t'):
            group.append(line)
        else:
            if group:
                groups.append(group)
            group = [line]

    for group in groups:
        mac = get_active_mac(group)
        if mac:
            return mac

def getserial():
    # get disk serial number plan 1
    try:
        output = subprocess.check_output('ioreg -rd1 -w0 -c AppleAHCIDiskDriver | grep Serial', shell=True)
        m = re.search('"Serial Number" = "(.*?)"', output)
        s = m.group(1).strip()
        return s
    except:
        pass

    # get disk serial number plan 2
    try:
        output = subprocess.check_output('ioreg -rd1 -w0 -c AppleS1XController | grep Serial', shell=True)
        m = re.search('"Serial Number" = "(.*?)"', output)
        s = m.group(1).strip()
        return s
    except:
        pass

    # get mac serial number
    try:
        cmd = 'ioreg -rd1 -w0 -c IOPlatformExpertDevice  | awk -F\\" \'/IOPlatformSerialNumber/{print $(NF-1)}\''
        s = subprocess.check_output(cmd, shell=True).strip()
        return "mac_" + s
    except:
        pass

    return '';

def getenc(input):
    path = os.path.abspath(os.path.join(os.path.dirname(__file__), './helper'))
    args = [path, 'getenc']
    proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    try:
        out, _ = proc.communicate(d(input))
    except:
        proc.kill()
        return ''
    return out

def getsign(input):
    path = os.path.abspath(os.path.join(os.path.dirname(__file__), './helper'))
    args = [path, 'getsign']
    proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    try:
        out, _ = proc.communicate(d(input))
    except:
        proc.kill()
        return ''
    return out

def d(txt):
    # return t(txt[:10], txt[10:])
    return txt

def t(h, txt):
    j = 0
    s = 1
    chars = []
    for c in [int(txt[i:i+2], 16) for i in range(len(txt)) if i % 2 == 0]:
        chars.append(chr(c^ord(h[j])))
        j += s
        if j + s == -1 or j+s == len(h):
            s *= -1
    return ''.join(chars)

class HTTPMessage(object):
    def __init__(self, method, path, headers, body=None, ver=None):
        self.path = path
        self.method = method
        self.headers = headers
        self.body = body
        self.ver = ver

def server():
    for req in parseHTTP(sys.stdin):
        ret = execute_command(req.path[1:], req.body)
        if ret:
            response(req.ver, ret)

def parseHTTP(f):
    method, path, ver = f.readline().strip().split(' ')
    method = method.upper()
    headers = []
    line = f.readline()
    body_len = 0
    while line != SEP:
        pair = line.split(': ')
        headers.append(pair)
        if pair[0].lower() == 'content-length':
            body_len = int(pair[1])
        line = f.readline()

    body = None
    if body_len:
        body = f.read(body_len)

    yield HTTPMessage(method, path, headers, body, ver)

def execute_command(subcommand, input=''):
    ret = None
    if subcommand == 'version':
        ret = VERSION
    elif subcommand == 'getserial':
        ret = getserial()
    elif subcommand == 'getmac':
        ret = getmac()
    elif subcommand == 'getenc':
        ret = getenc(input)
    elif subcommand == 'getsign':
        ret = getsign(input)
    return ret

if __name__ == '__main__':
    parser = argparse.ArgumentParser(prog='loginhelper')
    parser.add_argument('subcommand', nargs='?', help='subcommand')
    args = parser.parse_args()
    subcommand = args.subcommand
    ret = None
    if not subcommand:
        server()
    else:
        msg = None
        if subcommand == 'getenc' or subcommand == 'getsign':
            msg = raw_input()
        ret = execute_command(subcommand, msg)
        if ret:
            print(ret)
