"""
mbed SDK
Copyright (c) 2011-2015 ARM Limited

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""

import os
import json
import uuid
import lockfile
from os.path import expanduser

HOME_DIR = expanduser("~")
GREENTEA_HOME_DIR = ".mbed-greentea"
GREENTEA_GLOBAL_LOCK = "glock.lock"
GREENTEA_KETTLE = "kettle.json" # active Greentea instances
GREENTEA_KETTLE_PATH = os.path.join(HOME_DIR, GREENTEA_HOME_DIR, GREENTEA_KETTLE)


def greentea_home_dir_init():
    """ Initialize data in home directory for locking features
    """
    if not os.path.isdir(os.path.join(HOME_DIR, GREENTEA_HOME_DIR)):
        os.mkdir(os.path.join(HOME_DIR, GREENTEA_HOME_DIR))

def greentea_get_app_sem():
    """ Obtain locking mechanism info
    """
    greentea_home_dir_init()
    gt_instance_uuid = str(uuid.uuid4())   # String version
    gt_file_sem_name = os.path.join(HOME_DIR, GREENTEA_HOME_DIR, gt_instance_uuid)
    gt_file_sem = lockfile.LockFile(gt_file_sem_name)
    return gt_file_sem, gt_file_sem_name, gt_instance_uuid

def greentea_get_target_lock(target_id):
    file_path = os.path.join(HOME_DIR, GREENTEA_HOME_DIR, target_id)
    lock = lockfile.LockFile(file_path)
    return lock

def greentea_get_global_lock():
    file_path = os.path.join(HOME_DIR, GREENTEA_HOME_DIR, GREENTEA_GLOBAL_LOCK)
    lock = lockfile.LockFile(file_path)
    return lock

def greentea_update_kettle(greentea_uuid):
    from time import gmtime, strftime

    with greentea_get_global_lock():
        current_brew = get_json_data_from_file(GREENTEA_KETTLE_PATH)
        if not current_brew:
            current_brew = {}
        current_brew[greentea_uuid] = {
            "start_time" : strftime("%Y-%m-%d %H:%M:%S", gmtime()),
            "cwd" : os.getcwd(),
            "locks" : []
        }
        with open(GREENTEA_KETTLE_PATH, 'w') as kettle_file:
            json.dump(current_brew, kettle_file, indent=4)

def greentea_clean_kettle(greentea_uuid):
    """ Clean info in local file system config file
    """
    with greentea_get_global_lock():
        current_brew = get_json_data_from_file(GREENTEA_KETTLE_PATH)
        if not current_brew:
            current_brew = {}
        current_brew.pop(greentea_uuid, None)
        with open(GREENTEA_KETTLE_PATH, 'w') as kettle_file:
            json.dump(current_brew, kettle_file, indent=4)

def greentea_acquire_target_id(target_id, gt_instance_uuid):
    """ Acquire lock on target_id for given greentea UUID
    """
    with greentea_get_global_lock():
        current_brew = get_json_data_from_file(GREENTEA_KETTLE_PATH)
        if current_brew:
            current_brew[gt_instance_uuid]['locks'].append(target_id)
            with open(GREENTEA_KETTLE_PATH, 'w') as kettle_file:
                json.dump(current_brew, kettle_file, indent=4)

def greentea_acquire_target_id_from_list(possible_target_ids, gt_instance_uuid):
    """ Acquire lock on target_id from list of possible target_ids for given greentea UUID
    """
    target_id = None
    already_locked_target_ids = []
    with greentea_get_global_lock():
        current_brew = get_json_data_from_file(GREENTEA_KETTLE_PATH)
        # Get all already locked target_id
        for cb in current_brew:
            locks_list = current_brew[cb]['locks']
            already_locked_target_ids.extend(locks_list)

        # Remove from possible_target_ids elements from already_locked_target_ids
        available_target_ids = [item for item in possible_target_ids if item not in already_locked_target_ids]

        if available_target_ids:
            target_id = available_target_ids[0]
            current_brew[gt_instance_uuid]['locks'].append(target_id)
            with open(GREENTEA_KETTLE_PATH, 'w') as kettle_file:
                json.dump(current_brew, kettle_file, indent=4)
    return target_id

def greentea_release_target_id(target_id, gt_instance_uuid):
    """ Release target_id for given greentea UUID
    """
    with greentea_get_global_lock():
        current_brew = get_json_data_from_file(GREENTEA_KETTLE_PATH)
        if current_brew:
            current_brew[gt_instance_uuid]['locks'].remove(target_id)
            with open(GREENTEA_KETTLE_PATH, 'w') as kettle_file:
                json.dump(current_brew, kettle_file, indent=4)

def get_json_data_from_file(json_spec_filename, verbose=False):
    """ Loads from file JSON formatted string to data structure
    """
    result = None
    try:
        with open(json_spec_filename, 'r') as data_file:
            try:
                result = json.load(data_file)
            except ValueError:
                result = None
    except IOError:
        result = None
    return result

def greentea_kettle_info():
    """ generates human friendly info about current cettle state

    @details
    {
        "475a46d0-41fe-41dc-b5e6-5197a2fcbb28": {
            "locks": [],
            "start_time": "2015-10-23 09:29:54",
            "cwd": "c:\\Work\\mbed-drivers"
        }
    }
    """
    from prettytable import PrettyTable
    with greentea_get_global_lock():
        current_brew = get_json_data_from_file(GREENTEA_KETTLE_PATH)
        cols = ['greentea_uuid', 'start_time', 'cwd', 'locks']
        pt = PrettyTable(cols)

        for col in cols:
            pt.align[col] = "l"
        pt.padding_width = 1 # One space between column edges and contents (default)

        row = []
        for greentea_uuid in current_brew:
            kettle = current_brew[greentea_uuid]
            row.append(greentea_uuid)
            row.append(kettle['start_time'])
            row.append(kettle['cwd'])
            row.append('\n'.join(kettle['locks']))
            pt.add_row(row)
            row = []
    return pt.get_string()
