#!/usr/bin/env python3
#
#@file mrt-ble
#@brief python script to generate code for gatt profile
#@author Jason Berger
#@date 03/20/2020
#

import sys
import os
from mako.template import Template
import yaml
import json
import argparse
import pkgutil
from mrtutils.mrtTemplateHelper import *
from mrtutils.gatt_profile import GattProfile
from mrtutils.updates import *
from mrtutils.modsync import *


supported_platforms = ['mrt', 'esp32']


# Initialize the argument parser
def init_args():
    global parser
    parser = argparse.ArgumentParser("Tool to generate code for ble profile")
    parser.add_argument('-i', '--input', type=str, help='input file to parse', default="")
    parser.add_argument('-o', '--output', type=str, help='Output path', default="")
    parser.add_argument('-d', '--document', type=str, help='documentation path', default="")
    parser.add_argument('-t', '--template', type=str, help='path to create template', default="")
    parser.add_argument('-p', '--platform', type=str, help='platform of target', default="mrt")
    parser.add_argument('-n', '--nrf', action='store_true', help='Generates definition file for nrf connect', default=False)
    parser.add_argument('-m', '--html', action='store_true', help='Generates html ICD', default=False)
    parser.add_argument('-r', '--rst', action='store_true', help='Generates rst ICD', default=False)
    

def buildTemplate(object, templateFile, outputFile, userBlocks = True, overwrite= True):
    exists= False
    if not os.path.exists(outputFile):
        exists = True 

    if exists and overwrite == False:
        return 0


    cr = CodeReplacer()
    newContents =""
    headerPattern = r"@file (.*?)\n(.*?)\*/"
    handlerPattern = r" (.*?)_handler.*?\n}"
    if os.path.isfile(outputFile) and userBlocks:
        exists = True
        curFile = open(outputFile, "r")
        text = curFile.read()
        cr.loadText(text)
        cr.loadText(text,headerPattern)
        cr.loadText(text,handlerPattern)

    template = Template(pkgutil.get_data('mrtutils',templateFile) )
    newContents = "\n".join(template.render(obj = object, t = TemplateHelper()).splitlines())
    if(userBlocks):
        newContents = cr.insertBlocks(newContents)
        newContents = cr.insertBlocks(newContents,headerPattern)
        newContents = cr.insertBlocks(newContents,handlerPattern)
        cr.printDrops()
    text_file = open( outputFile , "w")
    text_file.write(newContents)
    text_file.close()

def buildProfileSource(gatt , outputPath, baseName =''):

    if baseName == '':
        baseName = gatt.name.lower() 
    
    if not os.path.exists(outputPath):
        os.makedirs(outputPath)
    
    if not os.path.exists(outputPath +"/svc"):
        os.makedirs(outputPath+"/svc")

    buildTemplate(gatt, 'templates/ble/profile_header.h', outputPath +"/"+gatt.name.lower() + "_profile.h" )
    buildTemplate(gatt, 'templates/ble/profile_source.c', outputPath +"/"+gatt.name.lower() + "_profile.c" )

    for service in gatt.services:
        print("***" + service.name + "****")
        buildTemplate(service, 'templates/ble/service_header.h', outputPath +"/svc/"+service.prefix + "_svc.h", False  )
        buildTemplate(service, 'templates/ble/service_source.c', outputPath +"/svc/"+service.prefix + "_svc.c", False )
        buildTemplate(service, 'templates/ble/app_service_source.c', outputPath +"/app_" + service.prefix+"_svc.c" )


def buildProfileSourceEsp32(gatt , outputPath, baseName =''):

    if baseName == '':
        baseName = gatt.name.lower() 
    
    if not os.path.exists(outputPath):
        os.makedirs(outputPath)
    
    if not os.path.exists(outputPath +"/svc"):
        os.makedirs(outputPath+"/svc")
    
    if not os.path.exists(outputPath +"/interface"):
        os.makedirs(outputPath+"/interface")



    copyRepoFile("https://github.com/uprev-mrt/platform-esp32.git", "/ble/esp32_gatt_adapter.h", outputPath +"/interface/esp32_gatt_adapter.h")
    copyRepoFile("https://github.com/uprev-mrt/platform-esp32.git", "/ble/esp32_gatt_adapter.c", outputPath +"/interface/esp32_gatt_adapter.c")

    copyRepoFile("https://github.com/uprev-mrt/utility-gatt-interface.git", "mrt_gatt_interface.c", outputPath +"/interface/mrt_gatt_interface.c")
    copyRepoFile("https://github.com/uprev-mrt/utility-gatt-interface.git", "mrt_gatt_interface.h", outputPath +"/interface/mrt_gatt_interface.h")

    buildTemplate(gatt, 'templates/ble/esp32/gatt_server.h', outputPath +"/{0}_gatt_server.h".format(gatt.name.lower()) )
    buildTemplate(gatt, 'templates/ble/esp32/gatt_server.c', outputPath +"/{0}_gatt_server.c".format(gatt.name.lower() ))
    buildTemplate(gatt, 'templates/ble/esp32/component.mk', outputPath +"/component.mk")
    #buildTemplate(gatt, 'templates/ble/esp32/kconfig', outputPath +"/kconfig")
    buildTemplate(gatt, 'templates/ble/esp32/CMakeLists.txt', outputPath +"/CMakeLists.txt")

    for service in gatt.services:
        print("***" + service.name + "****")
        buildTemplate(service, 'templates/ble/service_header.h', outputPath +"/svc/"+service.prefix + "_svc.h", False  )
        buildTemplate(service, 'templates/ble/service_source.c', outputPath +"/svc/"+service.prefix + "_svc.c", False )
        buildTemplate(service, 'templates/ble/app_service_source.c', outputPath +"/app_" + service.prefix+"_svc.c" )




def main():
    global path
    global parser
    global args

    updateCheck()

    init_args()
    args= parser.parse_args()
    argCount = len(sys.argv)
    

    inputFile = args.input
    path = args.output
    docPath = args.document
    templatePath = args.template

    gatt = GattProfile()

    gatt.platform = args.platform.lower()

    if not templatePath =="":
        templatePath.replace("yml","") 
        contents = pkgutil.get_data('mrtutils','templates/ble/gatt_descriptor_template.yml')
        text_file = open( templatePath + '.yml' , "w")
        text_file.write(contents.decode("utf-8"))
        text_file.close()
        sys.exit()


    if inputFile == "":
        print("No input file specified, use -t to create a template file")
        sys.exit()

    if not gatt.platform in supported_platforms:
        print("Unregconized platform: {0}".format(gatt.platform))
        print("Supported Platforms: {0}".format(supported_platforms))
        sys.exit()

    if os.path.isfile(inputFile):


        # if os.path.isfile(inputFile):
        print("Parsing " + inputFile )
        gatt.parseYaml(inputFile)
        gatt.hash = 'na'
        

        print("Validating {0} Profile".format( gatt.name))

        if not gatt.validate():
            print("Error found in Descriptor file")
            sys.exit()

        if not path == "":
            print("Generating Source")

            if not os.path.exists(path):
                os.makedirs(path)
            
            if gatt.platform == 'mrt':
                buildProfileSource(gatt, path)
            elif gatt.platform == 'esp32':
                buildProfileSourceEsp32(gatt, path)



   
        gatt.json = json.dumps(gatt.getDict(), indent=2)
        #print(s)

        if args.nrf:
            buildTemplate(gatt, 'templates/ble/nrf_definitions.json', path +"/" + gatt.name+"_definitions.json" )


        if not docPath == "":
            print("Generating Docs")

            if not os.path.exists(docPath):
                os.makedirs(docPath)

            if args.html :
                buildTemplate(gatt, 'templates/ble/gatt_icd.html', docPath +"/" + gatt.name+"_gatt_icd.html", False )
            
            if args.rst:
                buildTemplate(gatt, 'templates/ble/gatt_icd.rst', docPath +"/" + gatt.name+"_gatt_icd.rst" )

            buildTemplate(gatt, 'templates/ble/smart_icd.html', docPath +"/" + gatt.name+"_live_icd.html", False )
        


if __name__ == "__main__":
    main()