{{
import datetime
import malcat
from helpers import naturalsize

def pval(key, val=None, fmt="{}", va=False, pa=False, rva=False, size=False, kalign=30, valign=0, formated=False):
    r = "[normal]{}[/normal]:".format(key)
    lr = len(r) - 17
    if lr < kalign:
        r += (" "*(kalign-lr))
    if isinstance(val, malcat.StructAccess) or isinstance(val, malcat.FieldAccess):
        if val.has_enum and val.enum:
            d = "[color6]{}[/color6]([dim]{}[/dim])".format(val.enum, fmt.format(val.value))
            formated = True
            ld = len(d) - len("[color3][/color3][dim][/dim]")
        else:
            if size:
                d = naturalsize(val.value, binary=True)
            else:
                toprint = val.value
                if type(toprint) == str:
                    toprint = toprint.replace("[", "\\[")
                d = fmt.format(toprint)
            ld = len(d)
        val = val.value
    elif size and type(val) == int:
        d = naturalsize(val, binary=True)
        ld = len(d)
    elif isinstance(val, datetime.datetime):
        d = val.strftime("%Y-%m-%d %H:%M:%S")
        ld = len(d)
    else:
        d = fmt.format(val)
        ld = len(d)
    if not formated:
        if type(val) == int: 
            if val == 0:
                grp = "dim"
            elif pa:
                grp = "fa"
            elif rva:
                grp = "rva"
            elif va:
                grp = "va"
            else:
                grp = "normal"
        else:
            grp = "normal"
        d = "[{}]{}[/{}]".format(grp,d,grp)
    if ld < valign:
        d += (" "*(valign-ld))
    write(r+d)  

def bitfieldpp(fa):
    s = []
    for i in range(fa.count - 1, -1, -1):
        bit = fa.at(i)
        if bit.value:
            s.append("[color5]{}[/color5]([dim]{:X}[/dim])".format(bit.name, 1 << i))
    if s:
        return  " + ".join(s)
    else:
        return "[dim]0[/dim]"

def pbitfield(key, fa, kalign=30):    
    r = "[normal]{}[/normal]:".format(key)
    lr = len(r) - 17
    if lr < kalign:
        r += (" "*(kalign-lr))
    write(r + bitfieldpp(fa))
}}
{{
num_files = 0
for s in analysis.struct:
    if s.name == "CentralDirectory":
        num_files += 1

disk_number = 0
comment = ""
if "EndOfCentralDirectory" in analysis.struct:
    eof = analysis.struct.EndOfCentralDirectory
    disk_number = eof["DiskNumber"]
    if "Comment" in eof:
        comment = eof["Comment"]
if "EndOfCentralDirectory64" in analysis.struct:
    eof = analysis.struct.EndOfCentralDirectory64
    disk_number = eof["DiskNumber"]
encrypted = False
for s in analysis.struct:
    if "Flags" in s and s["Flags"]["EncryptedFile"]:
        encrypted = True
        break
num_files_displayed = 0
}}

[color1]Archive[/color1]
  {{ pval("Number of Files", num_files, "{:d}", valign=24) }} {{ pval("Disk number", disk_number, "#{:d}") }}
  {{ pval("Encrypted", encrypted and "yes" or "no", "{}", valign=24) }} {{ pval("Zip64", "EndOfCentralDirectory64" in analysis.struct and "yes" or "no", "{}") }}
  {{ pval("Comment", comment or "-", "{}") }}

[color1]Files[/color1]
{{for i, s in enumerate(analysis.struct):}}
{{if s.name == "CentralDirectory":}}
{{
if num_files_displayed > 128:
    write("[block1] ... and more ...[/block1]")
    break
num_files_displayed += 1
}}
  [vfile]{{write(s["FileName"].replace("[", "\\["))}}[/vfile]
{{
comp = s["CompressedSize"]
uncomp = s["UncompressedSize"]
if comp == 0xffffffff and "Zip64ExtraField" in s:
    comp = s["Zip64ExtraField"]["CompressedSize"]
if uncomp == 0xffffffff and "Zip64ExtraField" in s:
    uncomp = s["Zip64ExtraField"]["UncompressedSize"]
}}
    {{ pval("File size", uncomp, size=True, kalign=28, valign=24) }} {{ pval("Compressed size", "[normal]{}[/normal] bytes (ratio {}%)".format(naturalsize(comp, binary=True), uncomp * 100 // (comp or 1))) }}
    {{ pval("Compression", s.CompressionMethod, "{}", kalign=28, valign=24) }} 
    {{ pval("Header offset", s.LocalFileOffset, "{:x}", kalign=28, valign=24, pa=True) }} {{ pval("Attributes", s.ExternalAttributes, "0x{:x}") }}
    {{ pval("PKZip version", ".".join(str(s["Version"])), "{}", kalign=28, valign=24) }} {{ pval("PKZIP version needed", ".".join(str(s["VersionNeeded"])), "{}") }}
    {{ pval("Modification time", s.ModificationTime.value, kalign=28, valign=24) }} {{ pval("OperatingSystem", s.OperatingSystem, "{}") }}
    {{ pbitfield("Flags", s.Flags, kalign=28) }}
    {{ pval("Comment", "Comment" in s and s.Comment or "-", "{}", kalign=28) }}

{{:endif}}
{{:endfor}}
