#
# Copyright 2015 Philadelphia authors
#
# Licensed 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.
#
import typing

from . import etree
from . import model
from . import source


def read_messages(filename: str) -> typing.List[model.Message]:
    def message(elem: etree.Element) -> model.Message:
        name = etree.get(elem, 'name')
        msgtype = etree.get(elem, 'msgtype')
        return model.Message(name=name, msg_type=msgtype)
    tree = etree.parse(filename)
    return [message(elem) for elem in tree.findall('./messages/message')]


def read_fields(filename: str) -> typing.List[model.Field]:
    tree = etree.parse(filename)
    return sorted([_read_field(elem) for elem in tree.findall('./fields/field')],
                  key=lambda field: int(field.tag))


def read_enumerations(filename: str) -> typing.List[model.Enumeration]:
    def enumeration(elem: etree.Element) -> model.Enumeration:
        field = _read_field(elem)
        type_ = _read_type(elem)
        values = _read_values(elem)
        return model.Enumeration(primary_field=field, secondary_fields=[], type_=type_, values=values)
    tree = etree.parse(filename)
    return sorted([enumeration(elem) for elem in tree.findall('./fields/field') if _has_values(elem)],
                  key=lambda enumeration: int(enumeration.primary_field.tag))


READER = source.Reader(read_enumerations, read_fields, read_messages)


_TYPES = {
    'CHAR': 'char',
    'INT': 'int',
    'MULTIPLECHARVALUE': 'char',
    'MULTIPLESTRINGVALUE': 'String',
    'NUMINGROUP': 'int',
    'STRING': 'String',
}


def _read_field(elem: etree.Element) -> model.Field:
    number = etree.get(elem, 'number')
    name = etree.get(elem, 'name')
    return model.Field(tag=number, name=name)


def _read_type(elem: etree.Element) -> str:
    type_ = etree.get(elem, 'type')
    return _TYPES.get(type_, 'String')


def _has_values(elem: etree.Element) -> bool:
    return etree.get(elem, 'name') != 'MsgType' and elem.find('value') is not None


def _read_values(root: etree.Element) -> typing.List[model.Value]:
    def value(elem: etree.Element) -> model.Value:
        enum = etree.get(elem, 'enum')
        description = etree.get(elem, 'description')
        return model.Value(name=description, value=enum)
    return [value(elem) for elem in root.findall('value')]

@@ -1435,21 +1435,22 @@
         
-type_
+values
  = _read
@@ -1446,28 +1446,30 @@
 ues = _read_
-type
+values
 (elem)%0A     
@@ -1463,38 +1463,37 @@
 s(elem)%0A        
-values
+type_
  = _read_values(
@@ -1481,35 +1481,41 @@
 pe_ = _read_
+type(elem, 
 values
-(elem
 )%0A        re
@@ -2272,24 +2272,58 @@
 tree.Element
+, values: typing.List%5Bmodel.Value%5D
 ) -%3E str:%0A  
@@ -2332,16 +2332,27 @@
 type_ = 
+_TYPES.get(
 etree.ge
@@ -2370,47 +2370,145 @@
 pe')
-%0A    return _TYPES.get(type_, 'String')
+, 'String')%0A    if type_ == 'char' and values and max(len(value.value) for value in values) %3E 1:%0A        return 'String'%0A    return type_
 %0A%0A%0Ad

Improve QuickFIX support