# Path: mgz/enums.py
# def DifficultyEnum(ctx):
#     """Difficulty Enumeration."""
#     return Enum(
#         ctx,
#         hardest=0,
#         hard=1,
#         moderate=2,
#         standard=3,
#         easiest=4,
#         extreme=5,
#         unknown=6
#     )
# 
# def PlayerTypeEnum(ctx):
#     """Player Type Enumeration."""
#     return Enum(
#         ctx,
#         absent=0,
#         closed=1,
#         human=2,
#         eliminated=3,
#         computer=4,
#         cyborg=5,
#         spectator=6
#     )
# 
# def AgeEnum(ctx):
#     """Age Enumeration."""
#     return Enum(
#         ctx,
#         what=-2,
#         unset=-1,
#         dark=0,
#         feudal=1,
#         castle=2,
#         imperial=3,
#         postimperial=4,
#         dmpostimperial=6,
#         default='unknown'
#     )
# 
# Path: mgz/util.py
# class Find(Construct):
#     """Find bytes, and read past them."""
# 
#     __slots__ = ["find", "max_length"]
# 
#     def __init__(self, find, max_length):
#         """Initiallize."""
#         Construct.__init__(self)
#         if not isinstance(find, list):
#             find = [find]
#         self.find = find
#         self.max_length = max_length
# 
#     def _parse(self, stream, context, path):
#         """Parse stream to find a given byte string."""
#         start = stream.tell()
#         read_bytes = ""
#         if self.max_length:
#             read_bytes = stream.read(self.max_length)
#         else:
#             read_bytes = stream.read()
#         candidates = []
#         for f in self.find:
#             match = re.search(f, read_bytes)
#             if not match:
#                 continue
#             candidates.append(match.end())
#         if not candidates:
#             raise RuntimeError('could not find bytes: {}'.format(f))
#         choice = min(candidates)
#         stream.seek(start + choice)
#         return choice
# 
# class Version(Enum):
#     """Version enumeration.
# 
#     Using consts from https://github.com/goto-bus-stop/recanalyst/blob/master/src/Model/Version.php
#     for consistency.
#     """
#     AOK = 1
#     AOC = 4
#     AOC10 = 5
#     AOC10C = 8
#     USERPATCH12 = 12
#     USERPATCH13 = 13
#     USERPATCH14 = 11
#     USERPATCH15 = 20
#     DE = 21
#     USERPATCH14RC2 = 22
#     MCP = 30
#     HD = 19
# 
# def find_save_version(ctx):
#     """Find save version."""
#     if 'save_version' not in ctx:
#         return find_save_version(ctx._)
#     return ctx.save_version
# 
# def find_version(ctx):
#     """Find version."""
#     if 'version' not in ctx:
#         return find_version(ctx._)
#     return ctx.version


from construct import (Array, Float32l, Int16ul, Int32sl, Int32ul, Padding,
                       PascalString, Peek, String, Struct, Bytes, If, IfThenElse)
from mgz.enums import DifficultyEnum, PlayerTypeEnum, AgeEnum
from mgz.util import Find, Version, find_save_version, find_version
    Padding(8),
    "map_id"/If(lambda ctx: ctx._._.version != Version.AOK, Int32ul),
    Peek("difficulty_id"/Int32ul),
    DifficultyEnum("difficulty"/Int32ul),
    "lock_teams"/Int32ul,
    If(lambda ctx: ctx._._.version == Version.DE,
        Struct(
            Padding(29),
            If(lambda ctx: find_save_version(ctx) >= 13.07, Padding(1)),
            If(lambda ctx: find_save_version(ctx) >= 13.34, Padding(132)),
            If(lambda ctx: find_save_version(ctx) >= 20.06, Padding(1)),
            If(lambda ctx: find_save_version(ctx) >= 20.16, Padding(4)),
            If(lambda ctx: find_save_version(ctx) >= 25.02, Padding(4*16)),
            If(lambda ctx: find_save_version(ctx) >= 25.06, Padding(4))
        )
    ),
    Array(9, "player_info"/Struct(
        "data_ref"/Int32ul,
        PlayerTypeEnum("type"/Int32ul),
        "name"/PascalString(lengthfield="name_length"/Int32ul)
    )),
    Padding(36),
    Padding(4),
    IfThenElse(lambda ctx: ctx._._.version == Version.DE,
        Struct(
            If(lambda ctx: find_save_version(ctx) < 13.34, Find(b'\x9a\x99\x99\x99\x99\x99\x01\x40', None)),   # double: 2.2
            If(lambda ctx: 25.06 > find_save_version(ctx) >= 13.34, Find(b'\x33\x33\x33\x33\x33\x33\x03\x40', None)),  # double: 2.4
            If(lambda ctx: 25.22 > find_save_version(ctx) >= 25.06, Find(b'\x00\x00\x00\x00\x00\x00\x04\x40', None)),  # double: 2.5
            If(lambda ctx: find_save_version(ctx) >= 25.22, Find(b'\xcd\xcc\xcc\xcc\xcc\xcc\x04\x40', None))  # double: 2.6
        ),

# Path: mgz/enums.py
# def DifficultyEnum(ctx):
#     """Difficulty Enumeration."""
#     return Enum(
#         ctx,
#         hardest=0,
#         hard=1,
#         moderate=2,
#         standard=3,
#         easiest=4,
#         extreme=5,
#         unknown=6
#     )
# 
# def PlayerTypeEnum(ctx):
#     """Player Type Enumeration."""
#     return Enum(
#         ctx,
#         absent=0,
#         closed=1,
#         human=2,
#         eliminated=3,
#         computer=4,
#         cyborg=5,
#         spectator=6
#     )
# 
# def AgeEnum(ctx):
#     """Age Enumeration."""
#     return Enum(
#         ctx,
#         what=-2,
#         unset=-1,
#         dark=0,
#         feudal=1,
#         castle=2,
#         imperial=3,
#         postimperial=4,
#         dmpostimperial=6,
#         default='unknown'
#     )
# 
# Path: mgz/util.py
# class Find(Construct):
#     """Find bytes, and read past them."""
# 
#     __slots__ = ["find", "max_length"]
# 
#     def __init__(self, find, max_length):
#         """Initiallize."""
#         Construct.__init__(self)
#         if not isinstance(find, list):
#             find = [find]
#         self.find = find
#         self.max_length = max_length
# 
#     def _parse(self, stream, context, path):
#         """Parse stream to find a given byte string."""
#         start = stream.tell()
#         read_bytes = ""
#         if self.max_length:
#             read_bytes = stream.read(self.max_length)
#         else:
#             read_bytes = stream.read()
#         candidates = []
#         for f in self.find:
#             match = re.search(f, read_bytes)
#             if not match:
#                 continue
#             candidates.append(match.end())
#         if not candidates:
#             raise RuntimeError('could not find bytes: {}'.format(f))
#         choice = min(candidates)
#         stream.seek(start + choice)
#         return choice
# 
# class Version(Enum):
#     """Version enumeration.
# 
#     Using consts from https://github.com/goto-bus-stop/recanalyst/blob/master/src/Model/Version.php
#     for consistency.
#     """
#     AOK = 1
#     AOC = 4
#     AOC10 = 5
#     AOC10C = 8
#     USERPATCH12 = 12
#     USERPATCH13 = 13
#     USERPATCH14 = 11
#     USERPATCH15 = 20
#     DE = 21
#     USERPATCH14RC2 = 22
#     MCP = 30
#     HD = 19
# 
# def find_save_version(ctx):
#     """Find save version."""
#     if 'save_version' not in ctx:
#         return find_save_version(ctx._)
#     return ctx.save_version
# 
# def find_version(ctx):
#     """Find version."""
#     if 'version' not in ctx:
#         return find_version(ctx._)
#     return ctx.version


# Path: mgz/header/scenario.py
from construct import (Array, Float32l, Int16ul, Int32sl, Int32ul, Padding,
                       PascalString, Peek, String, Struct, Bytes, If, IfThenElse)
from mgz.enums import DifficultyEnum, PlayerTypeEnum, AgeEnum
from mgz.util import Find, Version, find_save_version, find_version

    Padding(8),
    "map_id"/If(lambda ctx: ctx._._.version != Version.AOK, Int32ul),
    Peek("difficulty_id"/Int32ul),
    DifficultyEnum("difficulty"/Int32ul),
    "lock_teams"/Int32ul,
    If(lambda ctx: ctx._._.version == Version.DE,
        Struct(
            Padding(29),
            If(lambda ctx: find_save_version(ctx) >= 13.07, Padding(1)),
            If(lambda ctx: find_save_version(ctx) >= 13.34, Padding(132)),
            If(lambda ctx: find_save_version(ctx) >= 20.06, Padding(1)),
            If(lambda ctx: find_save_version(ctx) >= 20.16, Padding(4)),
            If(lambda ctx: find_save_version(ctx) >= 25.02, Padding(4*16)),
            If(lambda ctx: find_save_version(ctx) >= 25.06, Padding(4))
        )
    ),
    Array(9, "player_info"/Struct(
        "data_ref"/Int32ul,
        PlayerTypeEnum("type"/Int32ul),
        "name"/PascalString(lengthfield="name_length"/Int32ul)
    )),
    Padding(36),
    Padding(4),
    IfThenElse(lambda ctx: ctx._._.version == Version.DE,
        Struct(
            If(lambda ctx: find_save_version(ctx) < 13.34, Find(b'\x9a\x99\x99\x99\x99\x99\x01\x40', None)),   # double: 2.2
            If(lambda ctx: 25.06 > find_save_version(ctx) >= 13.34, Find(b'\x33\x33\x33\x33\x33\x33\x03\x40', None)),  # double: 2.4
            If(lambda ctx: 25.22 > find_save_version(ctx) >= 25.06, Find(b'\x00\x00\x00\x00\x00\x00\x04\x40', None)),  # double: 2.5
            If(lambda ctx: find_save_version(ctx) >= 25.22, Find(b'\xcd\xcc\xcc\xcc\xcc\xcc\x04\x40', None))  # double: 2.6
        ),

        "end_of_game_settings"/Find(b'\x9a\x99\x99\x99\x99\x99\xf9\\x3f', None)   # double: 1.6