# build.py
# pre-build script, setting up build environment and fetch hal file for user's board

import sys
import os
import os.path
import requests
from os.path import basename
from platformio import util
from SCons.Script import DefaultEnvironment

try:
    import configparser
except ImportError:
    import ConfigParser as configparser

# get platformio environment variables
env = DefaultEnvironment()
config = configparser.ConfigParser()
config.read("platformio.ini")

# get platformio project directory
prjdir = env.get("PROJECT_DIR")

# get platformio shared path
shareddir = os.path.join (prjdir, "shared")

# get hal path
haldir = os.path.join (shareddir, "hal")

# check if hal file is present in source directory
halconfig = config.get("board", "halfile")

# check if hal file is set by ENV CI_HALFILE
if os.getenv("CI_HALFILE"):
    # if set, use ENV CI_HALFILE
    print("CI_HALFILE ENV FOUND")
    # override halconfig
    halconfig = os.getenv("CI_HALFILE")

halconfigfile = os.path.join (haldir, halconfig)

if os.path.isfile(halconfigfile) and os.access(halconfigfile, os.R_OK):
    print("Parsing hardware configuration from " + halconfigfile)
else:
    sys.exit("Missing file " + halconfigfile + ", please create it! Aborting.")

# check if lmic config file is present in shared directory
lmicconfig = config.get("common", "lmicconfigfile")
lmicconfigfile = os.path.join (shareddir, lmicconfig)
if os.path.isfile(lmicconfigfile) and os.access(lmicconfigfile, os.R_OK):
    print("Parsing LMIC configuration from " + lmicconfigfile)
else:
    sys.exit("Missing file " + lmicconfigfile + ", please create it! Aborting.")

# check if lora key file is present in shared directory
lorakeyfile = os.path.join (shareddir, config.get("common", "lorakeyfile"))
if os.path.isfile(lorakeyfile) and os.access(lorakeyfile, os.R_OK):
    print("Parsing LORAWAN keys from " + lorakeyfile)
else:
    sys.exit("Missing file " + lorakeyfile + ", please create it! Aborting.")

# check if ota key file is present in shared directory
otakeyfile = os.path.join (shareddir, config.get("common", "otakeyfile"))
if os.path.isfile(otakeyfile) and os.access(otakeyfile, os.R_OK):
    print("Parsing OTA keys from " + otakeyfile)
else:
    sys.exit("Missing file " + otakeyfile + ", please create it! Aborting.")

# parse hal file
mykeys = {}
with open(halconfigfile) as myfile:
    for line in myfile:
        line2 = line.strip("// ")
        key, value = line2.partition(" ")[::2]
        mykeys[key.strip()] = str(value).strip()
myboard = mykeys["board"]
myuploadspeed = mykeys["upload_speed"]
env.Replace(BOARD=myboard)
env.Replace(UPLOAD_SPEED=myuploadspeed)
print('\033[94m' + "Target board: " + myboard + " @ " + myuploadspeed + "bps" + '\033[0m')

# re-set partition table
mypartitiontable = config.get("env", "board_build.partitions")
board = env.BoardConfig(myboard)
board.manifest['build']['partitions'] = mypartitiontable
print('\033[94m' + "Partition table: " + mypartitiontable + '\033[0m')

# parse ota key file
with open(otakeyfile) as myfile:
    for line in myfile:
        key, value = line.partition("=")[::2]
        mykeys[key.strip()] = str(value).strip()

# usage of paxexpress: see https://github.com/paxexpress/docs

# get paxexpress credentials from ota key file
user = mykeys["PAXEXPRESS_USER"]
repository = mykeys["PAXEXPRESS_REPO"]
apitoken = mykeys["PAXEXPRESS_API_TOKEN"]

# get paxexpress upload parameters from platformio environment
version = config.get("common", "release_version")
package, dummy = halconfig.partition(".")[::2]

# put paxexpress user credentials to platformio environment
env.Replace(PAXEXPRESS_USER=user)
env.Replace(PAXEXPRESS_REPO=repository)
env.Replace(PAXEXPRESS_API_TOKEN=apitoken)

# get runtime credentials and put them to compiler directive
env.Append(BUILD_FLAGS=[
    u'-DWIFI_SSID=\\"' + mykeys["OTA_WIFI_SSID"] + '\\"',
    u'-DWIFI_PASS=\\"' + mykeys["OTA_WIFI_PASS"] + '\\"',
    u'-DPAXEXPRESS_USER=\\"' + mykeys["PAXEXPRESS_USER"] + '\\"',
    u'-DPAXEXPRESS_REPO=\\"' + mykeys["PAXEXPRESS_REPO"] + '\\"',
    u'-DPAXEXPRESS_PACKAGE=\\"' + package + '\\"',
    u'-DARDUINO_LMIC_PROJECT_CONFIG_H=' + lmicconfig,
    u'-I \"' + shareddir + '\"'
    ])

# function for pushing new firmware to paxexpress storage using API
def publish_paxexpress(source, target, env):
    firmware_path = str(source[0])
    firmware_name = basename(firmware_path)
    url = "/".join([
        "https://pax.express", "content",
        user, repository, package, version, firmware_name
    ])

    print("Uploading {0} to PAX.express. Version: {1}".format(
        firmware_name, version))
    print(url)

    headers = {
        "Content-type": "application/octet-stream",
        "X-Bintray-Publish": "1",
        "X-Bintray-Override": "1"
    }

    r = None

    try:
        r = requests.put(url,
                         data=open(firmware_path, "rb"),
                         headers=headers,
                         auth=(user,apitoken))
        r.raise_for_status()
    except requests.exceptions.RequestException as e:
        sys.stderr.write("Failed to submit package: %s\n" %
                         ("%s\n%s" % (r.status_code, r.text) if r else str(e)))
        env.Exit(1)

    print("Firmware has been successfully published at PAX.express!")

# put build file name and upload command to platformio environment
env.Replace(
    PROGNAME="firmware_" + package + "_v%s" % version,
    UPLOADCMD=publish_paxexpress)
