#!/usr/bin/env python3

import sys
import os
import errno
import shutil
import uuid

root = os.path.dirname(sys.argv[0])

output_file = sys.argv[1]
sound_dir = sys.argv[2]
image_dir = sys.argv[3]

default_image_size = 451
nbr_nodes_bsize    = 2
nodes_sector_size  = 0x40

def add_resource(folder, bfile):
    print("\n##########################################################")
    print("Resources:")
    print("----------------------------------------------------------")
    count = 0
    for resfile in sorted(os.listdir(folder)):
        with open(folder + "/" + resfile, "rb") as sfile:
            print("Adding at offset {:#08x} resource: {}".format(bfile.tell(), resfile))
            count += 1
            res_data = sfile.read()
            res_size = len(res_data)
            bfile.write(res_data)
            aligned_size = (((res_size-1)//0x200) + 1) * 0x200
            if aligned_size - res_size > 0 :
                pad = ''.join("00" for i in range(aligned_size - res_size))
                print("   padding from {} to {} (len:{})"
                        .format(res_size, aligned_size, len(pad)))
                bfile.write(bytes.fromhex(pad))
    return count

def save_navigation(wheel_enabled, audio_autojmp, bfile):
    #wheel_enabled
    nbr_nodes_bin += nodeid.to_bytes(2, byteorder='big',signed=False)
    pad = ''.join("00" for i in  range(0x200 - navigation_size))

def crange(start, length):
    r = list(range(start+1, length))
    if start > 1:
        r += list(range(1, start))
    r += [0]
    return  r

def add_actions(nodes, bfile):
    print("\n##########################################################")
    print("Actions:")
    print("----------------------------------------------------------")
    for nodeid in range(nodes):
        action_sector = b''
        action_sector_size = 0

        for i in crange(nodeid, nodes):
            action_sector += i.to_bytes(2, byteorder='big', signed=False)
            action_sector_size += 2

        pad = ''.join("00" for i in range(0x200 - action_sector_size))
        action_sector += bytes.fromhex(pad)

        print("Adding at offset {:#08x} node#{} action".format(bfile.tell(), nodeid))
        bfile.write(action_sector)

def add_nodes(nodes, image_dir, sound_dir, bfile):
    print("\n##########################################################")
    print("Nodes:")
    print("----------------------------------------------------------")
    soundfiles = sorted(os.listdir(sound_dir))
    imagefiles = sorted(os.listdir(image_dir))

    nodes_start_sector = 0
    action_start_sector = nodes + nodes_start_sector
    image_start_sector  = nodes + action_start_sector
    audio_start_sector  = image_start_sector + \
        (len(imagefiles)*default_image_size)

    for nodeid in range(nodes):
        node_uuid = uuid.uuid4()
        print("Creating nodeId:{} as uuid:{}".format(nodeid, str(node_uuid)))

        node_sector = node_uuid.bytes

        if nodeid < len(imagefiles) :
            image_start = image_start_sector
            image_size = default_image_size
        else :
            image_start = 0xffffffff
            image_size  = 0xffffffff

        node_sector += \
            image_start.to_bytes(4, byteorder='big', signed=False)

        node_sector += \
            image_size.to_bytes(4, byteorder='big', signed=False)

        node_sector += \
            audio_start_sector.to_bytes(4, byteorder='big', signed=False)

        audio_size = 1 + \
            ((os.path.getsize(sound_dir+"/"+soundfiles[nodeid])-1)//0x200)

        node_sector += \
            audio_size.to_bytes(4, byteorder='big', signed=False)

        action_on_ok = action_start_sector
        ok_enabled = 1
        if nodeid == 0 :
            options_in_transition = 1
            chosen_option = 0
            action_on_home = 0xffff
            option_in_home_transition = 0xffff
            chosen_option_home = 0xffff
            wheel_enabled = 1
            home_enabled = 1
            paused_enabled = 0
            autojump_at_audio_ends_enabled = 0
        else:
            options_in_transition = nodes
            #chosen_option = nodeid-1
            chosen_option = 0
            action_on_home = 0xffff #TODO
            option_in_home_transition = 0xffff
            chosen_option_home = 0xffff
            wheel_enabled = 0
            #home_enabled = 0 #TODO
            home_enabled = 1 #TODO
            paused_enabled = 1
            autojump_at_audio_ends_enabled = 1

        node_sector += \
            action_on_ok.to_bytes(2, byteorder='big', signed=False)
        node_sector += \
            options_in_transition.to_bytes(2, byteorder='big', signed=False)
        node_sector += \
            chosen_option.to_bytes(2, byteorder='big', signed=False)
        node_sector += \
            action_on_home.to_bytes(2, byteorder='big', signed=False)
        node_sector += \
            option_in_home_transition.to_bytes(2, byteorder='big', signed=False)
        node_sector += \
            chosen_option_home.to_bytes(2, byteorder='big', signed=False)
        node_sector += \
            wheel_enabled.to_bytes(2, byteorder='big', signed=False)
        node_sector += \
            ok_enabled.to_bytes(2, byteorder='big', signed=False)
        node_sector += \
            home_enabled.to_bytes(2, byteorder='big', signed=False)
        node_sector += \
            paused_enabled.to_bytes(2, byteorder='big', signed=False)
        node_sector += \
            autojump_at_audio_ends_enabled.to_bytes(2, byteorder='big', signed=False)

        node_sector_size = len(node_sector)
        pad = ''.join("00" for i in range(0x200 - node_sector_size))
        node_sector += bytes.fromhex(pad)

        print("Adding at offset  {:#08x} node#{}".format(bfile.tell(), nodeid))
        print("     image start: {:#08x}".format((image_start+1)*0x200))
        print("     image size:  {:#08x}".format((image_size)*0x200))
        print("     audio start: {:#08x}".format((audio_start_sector+1)*0x200))
        print("     audio size:  {:#08x}".format((audio_size)*0x200))
        bfile.write(node_sector)

        image_start_sector  += image_size
        audio_start_sector  += audio_size
        action_start_sector += 1

with open(output_file, "wb") as bfile:
    nbr_nodes = 0
    for resfile in os.listdir(sound_dir):
        nbr_nodes += 1

    #Writing Header sector
    header = b''
    header += nbr_nodes.to_bytes(2, byteorder='big',signed=False)
    pad = ''.join("00" for i in range(0x200 - nbr_nodes_bsize))
    header += bytes.fromhex(pad)
    bfile.write(header)

    #Writing nodes and actions sectors
    add_nodes(nbr_nodes, image_dir, sound_dir, bfile)
    add_actions(nbr_nodes, bfile)

    #Writing resources sectors
    add_resource(image_dir, bfile)
    add_resource(sound_dir, bfile)

    #Writing footer sector
    with open(root + "/footer", "rb") as footer:
        footer_data = footer.read()
        bfile.write(footer_data)


    print("\n##############################################################")
    print("File {} created successfully with {} nodes"
            .format(output_file, nbr_nodes))
    print("##############################################################")

