{{
import datetime
import malcat
import itertools
from filetypes.UDF import *
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)
    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))

def pdecimaldatetime(fa):
    return  "{}-{}-{} {}:{}:{}".format(fa["Year"], fa["Month"], fa["Day"], fa["Hours"], fa["Minutes"], fa["Seconds"])

def pbinarydatetime(fa):
    return  "{:04d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}".format(fa["Year"], fa["Month"], fa["Day"], fa["Hours"], fa["Minutes"], fa["Seconds"])

def nice(s):
    return s.replace("[", "\\[").replace("\x00", "")

}}
{{
volumes = analysis.parser.volumes.values()
partitions = list(itertools.chain(*[v.partitions.values() for v in volumes]))
num_files = len(analysis.parser.filesystem)
num_files_displayed = 0
}}

[color1]Volumes[/color1]
{{for volume in volumes:}}
  [color2]{{write(nice(volume.descriptor["VolumeIdentifier"]["Value"]))}}[/color2] (#{{volume.descriptor["PrimaryVolumeDescriptorNumber"]}})
    {{ pval("Volume name", volume.descriptor["VolumeIdentifier"]["Value"], valign=24, kalign=28) }} {{ pval("Volume set", volume.descriptor["VolumeSetIdentifier"]["Value"]) }}
    {{ pval("Creator", volume.descriptor["ImplementationIdentifier"]["Identifier"], valign=24, kalign=28) }} {{ pval("Application", volume.descriptor["ApplicationIdentifier"]["Identifier"]) }}
    {{ pval("Creation time", pbinarydatetime(volume.descriptor["RecordingTime"]), valign=24, kalign=28) }} {{ pbitfield("Flags", volume.descriptor["Flags"]) }}

{{:endfor}}

[color1]Partitions[/color1]
{{for part in partitions:}}
  [color2]{{write(nice(part.name))}}
{{ if hasattr(part, "descriptor"): }}
    {{ pval("Location", part.descriptor["PartitionLocation"] * part.volume.block_size, "0x{:x}", pa=True, valign=24, kalign=28) }} {{ pval("Size", part.descriptor["PartitionSize"] * part.volume.block_size, size=True) }}
    {{ pval("Creator", part.descriptor["ImplementationIdentifier"]["Identifier"], valign=24, kalign=28) }} {{ pval("Access", part.descriptor.AccessType) }}
{{:else:}}
    {{ pval("Unique ID", part.file.descriptor["UniqueId"], valign=24, kalign=28) }} 
{{:endif}}

{{:endfor}}

[color1]Files[/color1]
{{for name, f in analysis.parser.filesystem.items():}}
  [vfile]{{write(nice(name))}}[/vfile]
    {{ pval("Type", f.descriptor.IcbTag.FileType, valign=24, kalign=28) }} {{ pval("Size", f.size, "{:d} bytes") }}
    {{ pval("Attribute time", pbinarydatetime(f.descriptor["AttributeTime"]), valign=24, kalign=28) }} {{ pval("Modification time", pbinarydatetime(f.descriptor["ModificationTime"])) }}
    {{ pval("Access time", pbinarydatetime(f.descriptor["AccessTime"]), valign=24, kalign=28) }} {{ pval("Unique ID", f.descriptor["UniqueId"]) }}
    {{ pval("UID", f.descriptor["Uid"], "{:x}", valign=24, kalign=28) }} {{ pval("GID", f.descriptor["Gid"], "{:x}") }}
    {{ pval("Permissions", oct(f.descriptor["Permissions"])[2:], valign=24, kalign=28) }} {{ pval("Link count", f.descriptor["LinkCount"], "{:d}") }}
{{
if num_files_displayed > 128:
    write("[block1] ... and more ...[/block1]")
    break
num_files_displayed += 1
}}

{{:endfor}}
