# Copyright 3D Control Systems, Inc. All Rights Reserved 2017-2019.
# Built in San Francisco.

# This software is distributed under a commercial license for personal,
# educational, corporate or any other use.
# The software as a whole or any parts of it is prohibited for distribution or
# use without obtaining a license from 3D Control Systems, Inc.

# All software licenses are subject to the 3DPrinterOS terms of use
# (available at https://www.3dprinteros.com/terms-and-conditions/),
# and privacy policy (available at https://www.3dprinteros.com/privacy-policy/)
import sh

import os
import sh
import logging

DEV = "/dev/"
SD = "sd"
MODEL_ID_LINE = "ID_MODEL_ID=6015"
VENDOR_ID_LINE = "ID_VENDOR_ID=1d50"
MOUNT_POINT = "/mnt/smoothie_sd"
FIRMWARE_PATH = "firmware/kodak_smoothieware_v2.bin"
SMOOTHIE_CONFIG_FILE_NAME = "config"


def find_sd():
    for device in os.listdir(DEV):
        if device.startswith(SD):
            full_device_name = DEV + device
            output = sh.udevadm("info", "-q", "property", "--name", DEV + full_device_name)
            if output and MODEL_ID_LINE in output and VENDOR_ID_LINE:
                return full_device_name


def call_sh_with_try(function, error_text, success_text):
    logger = logging.getLogger(__name__)
    try:
        # correct options should be inside /etc/fstab
        function()
    except sh.ErrorReturnCode:
        logger.exception(error_text)
        return False
    else:
        logger.info(success_text)
        return True


def mount_sd():
    logger = logging.getLogger(__name__)
    if not os.path.isdir(MOUNT_POINT):
        os.mkdir(MOUNT_POINT)
    if os.path.ismount(MOUNT_POINT):
        logger.info("Smoothieboard's SD card is already mounted. Skipping mounting...")
    device = find_sd()
    if not device:
        logger.error("Can't find smoothieboard sd card device")
        return False
    else:
        return call_sh_with_try(lambda: sh.mount(device, MOUNT_POINT), \
                "Smoothieboard's SD card mount failed", \
                "Smoothieboard's SD card mounted")


def umount_sd():
    return call_sh_with_try(lambda: sh.umount(MOUNT_POINT), \
        "Can't unmount Smoothieboard's SD card", \
        "Smoothieboard's SD card unmounted") 


def upload_firmware():
   result = call_sh_with_try(lambda: sh.cp(FIRMWARE_PATH, MOUNT_POINT + "/"), \
        "Smoothieware uploaded successfully", \
        "Smoothieware uploading failer") 
   if result:
       os.sync()
   return result


def read_config():
    config_path = os.path.join(MOUNT_POINT, SMOOTHIE_CONFIG_FILE_NAME)
    if os.path.isfile(config_path):
        with open(config_path) as f:
            return f.read()


def write_config(config_text):
    config_path = os.path.join(MOUNT_POINT, SMOOTHIE_CONFIG_FILE_NAME)
    if os.path.isfile(config_path):
        with open(config_path, "w") as f:
            f.write(config_text)
