#!/usr/bin/env python
# coding=UTF-8
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4


from httpclient import Cookie, Session
import sys
import time

def test(X):
    if not X:
        raise Exception('Test failed')

def parse_info(resp):
    print('Got info %s' % resp)
    dic={}
    for pair in resp.split(b'\n'):
        dic[pair.split(b'=')[0].decode()] = pair.split(b'=')[1].decode()
    #print("Parsed as ", dic)
    return dic

if len(sys.argv) < 3:
    print("Usage: (server|client|both) (fixed|renew|browser)")
    sys.exit(1)

def test_method_is(dic,method):
    v = dic['expiration']
    if method=='fixed':
        test(v=='0')
    elif method == 'renew':
        test(v=='1')
    else: # browser
        test(v=='2')

def general_tests(method):
    print("------------------- General Tests --------------------")
    session = Session()
    session.transmit('/new')
    cookie = session.received['sc']
    if method=='fixed' or method=='renew':
        test(cookie.max_age == '5')
    else:
        test(not cookie.max_age)
   
    test(cookie.domain == 'foo.bar')
    test(cookie.path == '/foo')

    time.sleep(2)

    session.transmit('/update')
    cookie = session.received['sc']
    
    if method=='fixed':
        test(int(cookie.max_age) < 5)
    elif method=='renew':
        test(int(cookie.max_age) == 5)
    
    test(session.transmit('/clear') == b'clear')
    test(session.received['sc'].max_age == '0')
    test(parse_info(session.transmit('/info'))['is_set_x']=='0')

    session.transmit('/new_short')
    if method!='browser':
        test(session.received['sc'].max_age == '1')
    session.transmit('/expose')
    test(session.received['sc_x'].value=='1')
    time.sleep(2)
    test(session.transmit('/is_expired') == b'expired')
    test(session.received['sc_x'].max_age=='0')
    test(session.received['sc'].max_age=='0')

    print("new")
    session.transmit('/new')
    print("expose")
    session.transmit('/expose')
    test(session.received['sc_x'].value=='1')
    print("update")
    session.transmit('/update')
    test(session.received['sc_x'].value=='2')
    print("clear")
    session.transmit('/clear')
    test(session.received['sc_x'].max_age=='0')
    session.transmit('/new')
    test(parse_info(session.transmit('/info'))['is_exposed_x']=='0')
    session.transmit('/expose')
    test(session.received['sc_x'].value=='1')
    test(parse_info(session.transmit('/info'))['is_exposed_x']=='1')
    session.transmit('/unexpose')
    test(session.received['sc_x'].max_age=='0')
    test(parse_info(session.transmit('/info'))['is_exposed_x']=='0')
    test('sc' in session.state)
    session.transmit('/clear')
    test(session.received['sc'].max_age=='0')
    test(not 'sc_x' in session.received)

    session.transmit('/new')
    dic = parse_info(session.transmit('/info'))
    test(dic['is_set_x']=='1')
    test(dic['age']=='5')
    test_method_is(dic,method)
    session.transmit('/fixed')
    test(int(session.received['sc'].max_age) > 3)
    test_method_is(parse_info(session.transmit('/info')),'fixed')
    time.sleep(2);
    test_method_is(parse_info(session.transmit('/info')),'fixed')
    test(not 'sc' in session.received)
    session.transmit('/renew')
    test(session.received['sc'].max_age=='5')
    test_method_is(parse_info(session.transmit('/info')),'renew')
    time.sleep(2);
    test_method_is(parse_info(session.transmit('/info')),'renew')
    test(session.received['sc'].max_age=='5')
    session.transmit('/browser')
    test(not session.received['sc'].max_age)
    test_method_is(parse_info(session.transmit('/info')),'browser')
    session.transmit('/clear')
    session.transmit('/new')
    test(parse_info(session.transmit('/info'))['age']=='5')
    session.transmit('/new_short')
    test(parse_info(session.transmit('/info'))['age']=='1')
    session.transmit('/clear')
    test(session.transmit('/api')==b'ok')



def reset_session(x):
    print("------------------- Reset Session --------------------")
    session=Session()
    session.transmit('/new')
    prev_cookie = session.state['sc'].value
    session.transmit('/reset')
    new_cookie = session.state['sc'].value
    test(prev_cookie != new_cookie)
    test(prev_cookie[0]=='I')
    test(new_cookie[0]=='I')
    test(parse_info(session.transmit('/info'))['is_set_x']=='1')
def no_replay(x):
    session=Session()
    session.transmit('/new')
    old_state = session.state
    session.transmit('/clear')
    session.state = old_state
    test(parse_info(session.transmit('/info'))['is_set_x']=='0')
def force_server(x):
    print("------------------- Force Server --------------------")
    session=Session()
    session.transmit('/new')
    session.transmit('/update')
    test(session.state['sc'].value[0]=='C')
    test(parse_info(session.transmit('/info'))['on_server']=='0')
    session.transmit('/on_server')
    test(session.state['sc'].value[0]=='I')
    test(parse_info(session.transmit('/info'))['on_server']=='1')
    session.transmit('/update')
    test(session.state['sc'].value[0]=='I')
    test(parse_info(session.transmit('/info'))['on_server']=='1')
    session.transmit('/not_on_server')
    test(session.state['sc'].value[0]=='C')
    test(parse_info(session.transmit('/info'))['on_server']=='0')
    session.transmit('/update')
    test(session.state['sc'].value[0]=='C')
    test(parse_info(session.transmit('/info'))['on_server']=='0')
def size_tests(x):
    print("------------------- Force Server --------------------")
    session=Session()
    session.transmit("/huge")
    test(session.state['sc'].value[0]=='I')
    session.transmit("/small")
    test(session.state['sc'].value[0]=='C')
    session=Session()
    session.transmit("/new")
    test(session.state['sc'].value[0]=='C')
    session.transmit("/huge")
    test(session.state['sc'].value[0]=='I')
    session.transmit("/on_server")
    test(session.state['sc'].value[0]=='I')
    session.transmit("/not_on_server")
    test(session.state['sc'].value[0]=='I')
    session.transmit("/small")
    test(session.state['sc'].value[0]=='C')

def alt_tests(x):
    print("------------------- Alternative Storage --------------------")
    session=Session();
    r=parse_info(session.transmit("/alt?x=a"));
    test(not ('sc' in session.state))
    test(r["is_set_x"]=='0')
    test(r['x']=="''")
    test('sid' in r)
    sid = r['sid']
    r=parse_info(session.transmit("/alt?sid=" + sid));
    test(not ('sc' in session.state))
    test(r["is_set_x"]=='1')
    test(r["x"]=="'a'");
    test('sid' in r)
    sid = r['sid']
    r=parse_info(session.transmit("/alt?x=2&sid=" + sid));
    test(not ('sc' in session.state))
    test(r["is_set_x"]=='1')
    test(r["x"]=="'a'");
    test('sid' in r)
    sid = r['sid']
    r=parse_info(session.transmit("/alt?sid=" + sid));
    test(not ('sc' in session.state))
    test(r["is_set_x"]=='1')
    test(r["x"]=="'2'");
    test('sid' in r)


method = sys.argv[2]


if sys.argv[1] == 'server':
    general_tests(method)
    reset_session(method)
    no_replay(method)
    alt_tests(method)
elif sys.argv[1] == 'client':
    general_tests(method)
    alt_tests(method)
elif sys.argv[1] == 'both':
    general_tests(method)
    size_tests(method)
    force_server(method)
    alt_tests(method)


