#!/usr/bin/python3

# Copyright (c) 2010 - 2017, Nordic Semiconductor ASA
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of Nordic Semiconductor ASA nor the names of its
#    contributors may be used to endorse or promote products derived from this
#    software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

# This script takes a CSV file exported from the Mesh Assigned Numbers spreadsheet
# and extracts the opcodes for the configuration model. It even adds documentation
# and tries to make the generated header file pretty.

import csv
import sys

messages = []
opcode_list = []

copyright = """
/* Copyright (c) Nordic Semiconductor. All Rights Reserved.
 *
 * The information contained herein is property of Nordic Semiconductor ASA.
 * Terms and conditions of usage are described in detail in NORDIC
 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
 *
 * Licensees are granted free, non-transferable use of the information. NO
 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
 * the file.
 *
 */
"""

docstring = """
/**
 * Configuration model opcodes.
 * This list is autogenerated from the Mesh assigned numbers spreadsheet, exported as a CSV file.
 *
 * To regenerate this list, first export the assigned numbers spreadsheet as a CSV file. You might
 * need to export several CSV files, because the spreadsheet contains multiple "sheets" with opcodes.
 * Then prepare the CSV files by removing the headers and concatenating the files. This can be done
 * by running `tail -n+3 opcodes.csv >> opcode_list.csv` for each of the exported files.
 */
"""

with open("config_model_messages.list", "r") as message_list_file:
    for line in message_list_file:
        messages = messages + [line.rstrip()]

with open("all_opcodes.csv", "r") as csvfile:
    reader = csv.reader(csvfile, delimiter=';')
    for row in reader:
        constant_name = "CONFIG_OPCODE_" + (row[1].upper().replace(" ", "_").replace("CONFIG_", ""))
        handler_name = "handle_" + row[1].lower().replace(" ", "_").replace("CONFIG_", "")
        for message in messages:
            if message == constant_name:
                opcode_list.append((constant_name, row[0], row[1], handler_name))

# We want an enum sorted by value:
opcode_list.sort(key = lambda t: int(t[1], 16))

with open("config_opcodes.h", "w") as outfile:
    outfile.write(copyright)
    outfile.write("#ifndef CONFIG_OPCODES_H__\n")
    outfile.write("#define CONFIG_OPCODES_H__\n")
    outfile.write("\n")
    outfile.write(docstring)
    outfile.write("typedef enum\n")
    outfile.write("{\n") # Not even scripts are excempted from the coding standard! (Brace on a line by itself)

    for opcode in opcode_list:
        outfile.write("    /** Opcode for the \"" + opcode[2] + "\" message. */\n")
        outfile.write("    " + opcode[0] + " = " + opcode[1] + ",\n")

    outfile.write("} config_opcode_t;\n")
    outfile.write("\n")
    outfile.write("#endif\n")

with open("handler_template.c", "w") as outfile:
    outfile.write(copyright)
    outfile.write("""
#include "access.h"
#include "config_opcodes.h"

/********** Opcode handler functions **********/
""")
    for opcode in opcode_list:
        outfile.write("static void " + opcode[3] + "(access_model_handle_t handle, const access_message_rx_t * p_message, void * p_args)\n")
        outfile.write("{\n")
        outfile.write("    /* TODO: Implement me please. Also remember to check if I'm supported in this model. */\n")
        outfile.write("}\n")
        outfile.write("\n")
    outfile.write("\n")

    outfile.write("""
/********** Opcode handler list *********/
static const access_opcode_handler_t opcode_handlers[] =
{
""")

    for opcode in opcode_list:
        outfile.write("    {{ .opcode = " + opcode[1] + ", .company_id = ACCESS_COMPANY_ID_NONE }, " + opcode[3] + " },\n")
    outfile.write("};\n")

