#!/usr/bin/env python

#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

r"""
PYTHONPATH=./gen-py:../../lib/py/build/lib... ./FastbinaryTest.py
"""

# TODO(dreiss): Test error cases.  Check for memory leaks.

from __future__ import print_function

import math
import os
import sys
import timeit

from copy import deepcopy
from pprint import pprint

from thrift.transport import TTransport
from thrift.protocol.TBinaryProtocol import TBinaryProtocol, TBinaryProtocolAccelerated
from thrift.protocol.TCompactProtocol import TCompactProtocol, TCompactProtocolAccelerated

from DebugProtoTest import Srv
from DebugProtoTest.ttypes import Backwards, Bonk, Empty, HolyMoley, OneOfEach, RandomStuff, Wrapper


class TDevNullTransport(TTransport.TTransportBase):
    def __init__(self):
        pass

    def isOpen(self):
        return True

ooe1 = OneOfEach()
ooe1.im_true = True
ooe1.im_false = False
ooe1.a_bite = 0xd6
ooe1.integer16 = 27000
ooe1.integer32 = 1 << 24
ooe1.integer64 = 6000 * 1000 * 1000
ooe1.double_precision = math.pi
ooe1.some_characters = "Debug THIS!"
ooe1.zomg_unicode = u"\xd7\n\a\t"

ooe2 = OneOfEach()
ooe2.integer16 = 16
ooe2.integer32 = 32
ooe2.integer64 = 64
ooe2.double_precision = (math.sqrt(5) + 1) / 2
ooe2.some_characters = ":R (me going \"rrrr\")"
ooe2.zomg_unicode = u"\xd3\x80\xe2\x85\xae\xce\x9d\x20"\
                    u"\xd0\x9d\xce\xbf\xe2\x85\xbf\xd0\xbe"\
                    u"\xc9\xa1\xd0\xb3\xd0\xb0\xcf\x81\xe2\x84\x8e"\
                    u"\x20\xce\x91\x74\x74\xce\xb1\xe2\x85\xbd\xce\xba"\
                    u"\xc7\x83\xe2\x80\xbc"

if sys.version_info[0] == 2 and os.environ.get('THRIFT_TEST_PY_NO_UTF8STRINGS'):
    ooe1.zomg_unicode = ooe1.zomg_unicode.encode('utf8')
    ooe2.zomg_unicode = ooe2.zomg_unicode.encode('utf8')

hm = HolyMoley(**{"big": [], "contain": set(), "bonks": {}})
hm.big.append(ooe1)
hm.big.append(ooe2)
hm.big[0].a_bite = 0x22
hm.big[1].a_bite = 0x22

hm.contain.add(("and a one", "and a two"))
hm.contain.add(("then a one, two", "three!", "FOUR!"))
if sys.version_info[0] == 2 and os.environ.get('THRIFT_TEST_PY_NO_UTF8STRINGS'):
    hm.contain.add((u"\xd7\n\a\t".encode('utf8'),))
else:
    hm.contain.add((u"\xd7\n\a\t",))
hm.contain.add(())

hm.bonks["nothing"] = []
hm.bonks["something"] = [
    Bonk(**{"type": 1, "message": "Wait."}),
    Bonk(**{"type": 2, "message": "What?"}),
]
hm.bonks["poe"] = [
    Bonk(**{"type": 3, "message": "quoth"}),
    Bonk(**{"type": 4, "message": "the raven"}),
    Bonk(**{"type": 5, "message": "nevermore"}),
]

rs = RandomStuff()
rs.a = 1
rs.b = 2
rs.c = 3
rs.myintlist = list(range(20))
rs.maps = {1: Wrapper(**{"foo": Empty()}), 2: Wrapper(**{"foo": Empty()})}
rs.bigint = 124523452435
rs.triple = 3.14

# make sure this splits two buffers in a buffered protocol
rshuge = RandomStuff()
rshuge.myintlist = list(range(10000))

my_zero = Srv.Janky_result(**{"success": 5})


class Test(object):
    def __init__(self, fast, slow):
        self._fast = fast
        self._slow = slow

    def _check_write(self, o):
        trans_fast = TTransport.TMemoryBuffer()
        trans_slow = TTransport.TMemoryBuffer()
        prot_fast = self._fast(trans_fast, fallback=False)
        prot_slow = self._slow(trans_slow)

        o.write(prot_fast)
        o.write(prot_slow)
        ORIG = trans_slow.getvalue()
        MINE = trans_fast.getvalue()
        if ORIG != MINE:
            print("actual  : %s\nexpected: %s" % (repr(MINE), repr(ORIG)))
            raise Exception('write value mismatch')

    def _check_read(self, o):
        prot = self._slow(TTransport.TMemoryBuffer())
        o.write(prot)

        slow_version_binary = prot.trans.getvalue()

        prot = self._fast(
            TTransport.TMemoryBuffer(slow_version_binary), fallback=False)
        c = o.__class__()
        c.read(prot)
        if c != o:
            print("actual  : ")
            pprint(repr(c))
            print("expected: ")
            pprint(repr(o))
            raise Exception('read value mismatch')

        prot = self._fast(
            TTransport.TBufferedTransport(
                TTransport.TMemoryBuffer(slow_version_binary)), fallback=False)
        c = o.__class__()
        c.read(prot)
        if c != o:
            print("actual  : ")
            pprint(repr(c))
            print("expected: ")
            pprint(repr(o))
            raise Exception('read value mismatch')

    def do_test(self):
        self._check_write(HolyMoley())
        self._check_read(HolyMoley())

        self._check_write(hm)
        no_set = deepcopy(hm)
        no_set.contain = set()
        self._check_read(no_set)
        self._check_read(hm)

        self._check_write(rs)
        self._check_read(rs)

        self._check_write(rshuge)
        self._check_read(rshuge)

        self._check_write(my_zero)
        self._check_read(my_zero)

        self._check_read(Backwards(**{"first_tag2": 4, "second_tag1": 2}))

        # One case where the serialized form changes, but only superficially.
        o = Backwards(**{"first_tag2": 4, "second_tag1": 2})
        trans_fast = TTransport.TMemoryBuffer()
        trans_slow = TTransport.TMemoryBuffer()
        prot_fast = self._fast(trans_fast, fallback=False)
        prot_slow = self._slow(trans_slow)

        o.write(prot_fast)
        o.write(prot_slow)
        ORIG = trans_slow.getvalue()
        MINE = trans_fast.getvalue()
        assert id(ORIG) != id(MINE)

        prot = self._fast(TTransport.TMemoryBuffer(), fallback=False)
        o.write(prot)
        prot = self._slow(
            TTransport.TMemoryBuffer(prot.trans.getvalue()))
        c = o.__class__()
        c.read(prot)
        if c != o:
            print("copy: ")
            pprint(repr(c))
            print("orig: ")
            pprint(repr(o))


def do_test(fast, slow):
    Test(fast, slow).do_test()


def do_benchmark(protocol, iters=5000, skip_slow=False):
    setup = """
from __main__ import hm, rs, TDevNullTransport
from thrift.protocol.{0} import {0}{1}
trans = TDevNullTransport()
prot = {0}{1}(trans{2})
"""

    setup_fast = setup.format(protocol, 'Accelerated', ', fallback=False')
    if not skip_slow:
        setup_slow = setup.format(protocol, '', '')

    print("Starting Benchmarks")

    if not skip_slow:
        print("HolyMoley Standard = %f" %
              timeit.Timer('hm.write(prot)', setup_slow).timeit(number=iters))

    print("HolyMoley Acceler. = %f" %
          timeit.Timer('hm.write(prot)', setup_fast).timeit(number=iters))

    if not skip_slow:
        print("FastStruct Standard = %f" %
              timeit.Timer('rs.write(prot)', setup_slow).timeit(number=iters))

    print("FastStruct Acceler. = %f" %
          timeit.Timer('rs.write(prot)', setup_fast).timeit(number=iters))


if __name__ == '__main__':
    print('Testing TBinaryAccelerated')
    do_test(TBinaryProtocolAccelerated, TBinaryProtocol)
    do_benchmark('TBinaryProtocol')
    print('Testing TCompactAccelerated')
    do_test(TCompactProtocolAccelerated, TCompactProtocol)
    do_benchmark('TCompactProtocol')
