#!python
#
# Script building the /init script
# Reads configuration file from :
#   - CMKINITCFG file if environment variable set
#   - /etc/cmkinitramfs.ini by default
#

import cmkinit
import configparser
import os

def get_data(data_dic, data_str):
    """Returns a data source from the data_dic dictionnary
    Parse data_str for:
      - "UUID=...": creates UuidData()
      - "PATH=...": creates PathData()
      - "DATA=...": search in data_dic for corresponding Data object
      - Other: same as "DATA=..."
    """
    if not data_str:
        return None
    if data_str[:5] == "UUID=":
        return cmkinit.UuidData(data_str[5:])
    elif data_str[:5] == "PATH=":
        return cmkinit.PathData(data_str[5:])
    elif data_str[:5] == "DATA=":
        return data_dic[data_str[5:]]
    else:
        return data_dic[data_str]


# Load configuration
config = configparser.ConfigParser()
if os.environ.get("CMKINITCFG"):
    config.read(os.environ["CMKINITCFG"])
else:
    config.read("/etc/cmkinitramfs.ini")

# datas: Dictionnary assigning data name to Data objects
datas = {k : None for k in config if k != "DEFAULT"}

# Create data objects
for data in datas:
    if config[data]["type"] == "luks":
        datas[data] = cmkinit.LuksData(get_data(datas, config[data]["source"]),
                                      config[data]["name"],
                                      get_data(datas, config[data].get("key")),
                                      get_data(datas, config[data].get("header")))
    elif config[data]["type"] == "lvm":
        datas[data] = cmkinit.LvmData(config[data]["vg-name"],
                                     config[data]["lv-name"])
    elif config[data]["type"] == "mount":
        datas[data] = cmkinit.MountData(get_data(datas, config[data]["source"]),
                                       config[data]["mountpoint"],
                                       config[data]["filesystem"],
                                       config[data].get("options", None))
    elif config[data]["type"] == "md":
        if "source" in config[data]:
            sources = [get_data(datas, config[data]["source"])]
        else:
            nb_sources = len([None for l in config[data] if l[:6] == "source"])
            sources = [get_data(datas, config[data][f"source{k}"]) \
                       for k in range(nb_sources)]
        datas[data] = cmkinit.MdData(sources, config[data]["name"])
    elif config[data]["type"] == "clone":
        datas[data] = cmkinit.CloneData(get_data(datas, config[data]["source"]),
                                        get_data(datas, config[data]["destination"]))
    else:
        raise Exception(f"Config type {config[data]['type']} does not exists")

# Configure dependencies
for data in datas:
    for dep in config[data]["need"].strip().split(','):
        if dep.strip():
            datas[data].add_dep(datas[dep.strip()])
    for ldep in config[data]["load-need"].strip().split(','):
        if ldep.strip():
            datas[data].add_load_dep(datas[ldep.strip()])

# Configure final data sources
for final in [config["DEFAULT"]["root"]] \
             + config["DEFAULT"]["mountpoints"].strip().split(','):
    if final.strip():
        datas[final.strip()].set_final()


# Begin generating /init

print(cmkinit.do_header(), end='')
print(cmkinit.do_init(), end='')
print(cmkinit.do_cmdline(), end='')
if config["DEFAULT"].get("keymap"):
    print(cmkinit.do_keymap(config["DEFAULT"].get("keymap-file",
                                                 "/root/keymap.bmap")),
          end='')
print(datas[config["DEFAULT"]["root"]].load(), end='')
print(cmkinit.do_maintenance(), end='')
for mountpoint in config["DEFAULT"]["mountpoints"].split(','):
    if mountpoint:
        print(datas[mountpoint].load(), end='')
print(
    cmkinit.do_switch_root(config["DEFAULT"].get("init", "/sbin/init"),
                           datas[config["DEFAULT"]["root"]]),
    end=''
)

