'''
Multipoint Application Sharing protocol (T.128)
'''
import functools, itertools, types, builtins, operator, sys, six

import ptypes, protocol.gcc as gcc
from ptypes import *

ptypes.setbyteorder(ptypes.config.byteorder.littleendian)

### atomic definitions
class Integer8(pint.uint8_t): pass
class Integer16(pint.uint16_t): pass
class Integer32(pint.uint32_t): pass

class Boolean8(pint.enum, Integer8):
    _values_ = [
        ('FALSE', 0x00),
        ('TRUE', 0x01),
    ]

class Boolean16(pint.enum, Integer16):
    _values_ = [
        ('FALSE', 0x0000),
        ('TRUE', 0x0001),
    ]

class ShareId(pstruct.type):
    class UserId(pint.enum, pint.littleendian(gcc.ChannelId)):
        '''default value is set to server channel id (1002)'''
        _values_ = [
            ('serverChannelId', 1002),
        ]
        def properties(self):
            res = super(ShareId.UserId, self).properties()
            if self.initializedQ():
                res['valid'] = self.valid()
            return res
        def default(self):
            return self.set(0x3ea)
        def valid(self):
            return self.copy().default().int() == self.int()
        def alloc(self, **attrs):
            return super(ShareId.UserId, self).alloc(**attrs).default()

    _fields_ = [
        (UserId, 'userId'),
        (pint.uint16_t, 'counter'),
    ]

    def alloc(self, **fields):
        res = super(ShareId, self).alloc(**fields)
        if 'userId' not in res:
            res['userId'].default()
        return res

    def summary(self):
        return "userId={:d} counter={:d}".format(self['userId'].int(), self['counter'].int())

class Coordinate16(Integer16): pass

### Container types
class Rectangle16(pstruct.type):
    _fields_ = [
        (Integer16, 'left'),
        (Integer16, 'top'),
        (Integer16, 'right'),
        (Integer16, 'bottom'),
    ]

### Lookup types
class PDUType(ptype.definition):
    cache = {}

    class type(pbinary.enum):
        length, _values_ = 4, [
            ('confirmActive', 3),
            ('data', 7),
            ('deactivateAll', 6),
            ('deactivateOther', 4),
            ('deactivateSelf', 5),
            ('demandActive', 1),
            ('requestActive', 2),
            ('serverRedirect', 10),
        ]

class CapabilitySetType(ptype.definition):
    cache = {}

    class Choice(pint.enum, pint.uint16_t):
        _values_ = [
            ('bitmapCacheCapabilitySet', 4),
            ('bitmapCapabilitySet', 2),
            ('colorCacheCapabilitySet', 10),
            ('controlCapabilitySet', 5),
            ('generalCapabilitySet', 1),
            ('orderCapabilitySet', 3),
            ('pointerCapabilitySet', 8),
            ('activationCapabilitySet', 7),
            ('shareCapabilitySet', 9),
        ]

class PDUType2(ptype.definition):
    cache = {}

    class type(pint.enum, pint.uint8_t):
        _values_ = [
            ('application', 25),
            ('control', 20),
            ('font', 11),
            ('flowResponse', 66),
            ('flowStop', 67),
            ('flowTest', 65),
            ('input', 28),
            ('mediatedControl', 29),
            ('pointer', 27),
            ('remoteShare', 30),
            ('synchronize', 31),
            ('update', 2),
            ('updateCapability', 32),
            ('windowActivation', 23),
            ('windowList', 24),
        ]

class PDUTypeFlow(ptype.definition):
    cache = {}
    class type(pint.enum, Integer16):
        _values_ = [
            ('response', 66),
            ('stop', 67),
            ('test', 65),
        ]

### capability set definitions
class OSMajorType(pint.enum, pint.uint16_t):
    _values_ = [
        ('unspecified', 0),
        ('windows', 1),
        ('os2', 2),
        ('macintosh', 3),
        ('unix', 4),
        ('ios', 5),
        ('osx', 6),
        ('android', 7),
        ('chromeOS', 8),
    ]

class OSMinorType(pint.enum, pint.uint16_t):
    _values_ = [
        ('unspecified', 0),
        ('windows-31x', 1),
        ('windows-95', 2),
        ('windows-NT', 3),
        ('oOS2-V21', 4),
        ('power-pc', 5),
        ('macintosh', 6),
        ('native-XServer', 7),
        ('pseudo-XServer', 8),
        ('windows-RT', 9),
    ]

@CapabilitySetType.define
class GeneralCapabilitySet(pstruct.type):
    type = 1

    class _protocolVersion(pint.enum, Integer16):
        _values_ = [
            ('TS_CAPS_PROTOCOLVERSION', 0x0200),
        ]
        def default(self):
            return self.set(0x0200)
        def valid(self):
            return self.copy().default().int() == self.int()
        def properties(self):
            res = super(GeneralCapabilitySet._protocolVersion, self).properties()
            res['valid'] = self.valid()
            return res

    @pbinary.littleendian
    class _extraFlags(pbinary.flags):
        _fields_ = [
            (5, 'unused0'),
            (1, 'NO_BITMAP_COMPRESSION_HDR'),
            (5, 'unused6'),
            (1, 'ENC_SALTED_CHECKSUM'),
            (1, 'AUTORECONNECT_SUPPORTED'),
            (1, 'LONG_CREDENTIALS_SUPPORTED'),
            (1, 'reserved'),
            (1, 'FASTPATH_OUTPUT_SUPPORTED'),
        ]

    _fields_ = [
        (OSMajorType, 'osMajorType'),
        (OSMinorType, 'osMinorType'),
        (_protocolVersion, 'protocolVersion'),
        (Integer16, 'pad2octetsA'),
        (Integer16, 'generalCompressionTypes'),
        (_extraFlags, 'extraFlags'),
        (Integer16, 'updatecapabilityFlag'),
        (Integer16, 'remoteUnshareFlag'),
        (Integer16, 'generalCompressionLevel'),
        (Integer16, 'pad2octetsC'),

        (Boolean16, 'refreshRectSupport'),
        (Boolean16, 'suppressOutputSupport'),
    ]

@pbinary.littleendian
class BitmapCompressionCapabilityFlags(pbinary.enum):
    length, _values_ = 16, [
        ('FALSE', 0x0000),
        ('TRUE', 0x0001),
    ]

@pbinary.littleendian
class DRAW_(pbinary.flags):
    _fields_ = [
        (3, 'unused'),
        (1, 'UNUSED_FLAG'),
        (1, 'ALLOW_SKIP_ALPHA'),
        (1, 'ALLOW_COLOR_SUBSAMPLING'),
        (1, 'ALLOW_DYNAMIC_COLOR_FIDELITY'),
        (1, 'RESERVED'),