#!/usr/bin/env python

__author__ = 'Holger Knust'

import codecs
import csv
import fnmatch
import logging
import os
import shutil
import sys
import time

# Global vars
logger = None
in_folder = None
out_folder = None
processed_folder = None
error_folder = None
ref_folder = None


def _get_files_by_extension(root_folder, file_ext_regex):
    matches = []
    for root, dir_names, file_names in os.walk(root_folder):
        for filename in fnmatch.filter(file_names, "*." + file_ext_regex):
            matches.append(os.path.join(root, filename))

    if matches:
        matches.sort()

    return matches


def get_csv_files(root_folder):
    return _get_files_by_extension(root_folder, "[cC][sS][vV]")


def setup_logging(log_file):
    global logger

    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    std_out = logging.StreamHandler(sys.stdout)
    std_out.setLevel(logging.DEBUG)
    std_out.setFormatter(formatter)
    logger.addHandler(std_out)

    file_handler = logging.FileHandler(log_file)
    file_handler.setFormatter(formatter)
    file_handler.setLevel(logging.WARN)
    logger.addHandler(file_handler)


def teardown_logging():
    global logger

    handlers = logger.handlers
    for handler in handlers:
        logger.removeHandler(handler)

def read_inventory_file(file_name, ean_dict):
    with codecs.open(file_name, "r", encoding='utf-8') as f:
        reader = csv.reader(f, delimiter=';')

        header_read = False
        ean_index = -1
        stock_index = -1
        for row in reader:
            if header_read:
                ean = row[ean_index]
                if len(ean) > 0:
                    stock = int(row[stock_index])

                    if ean in ean_dict:
                        ean_dict[ean] += stock
                    else:
                        ean_dict[ean] = stock
            else:
                header_read = True
                if "ean" in row:
                    ean_index = row.index("ean")
                if "stock" in row:
                    stock_index = row.index("stock")


def read_second_file(file_name):
    with codecs.open(file_name, "r", encoding='utf-8') as f:
        reader = csv.reader(f, delimiter=';')

        header_read = False
        ean_index = -1
        content_dict = dict()
        for row in reader:
            if header_read:
                ean = row[ean_index]
                if len(ean) > 0:
                    content_dict[ean] = row
            else:
                header_read = True
                if "VariationEAN" in row:
                    ean_index = row.index("VariationEAN")
                header = row

    return content_dict, header

def write_csv(file_name, header,  content_dict):
    with codecs.open(file_name, "w", encoding='utf-8') as of:
        writer = csv.writer(of, delimiter=';')

        writer.writerow(header)
        for key, row in content_dict.items():
            if len(row) < len(header):
                row += ["0","11"]
            writer.writerow(row)

def move_files(file_list, dest_folder):
    for file in file_list:
        try:
            shutil.move(file,dest_folder)
        except Exception as ex:
            logger.exception(ex)

def process(source_folder):
    global logger, in_folder, out_folder, processed_folder, error_folder, ref_folder

    second_file_name = "Dynamic_404.csv"
    csv_file_list = get_csv_files(source_folder)

    second_input_file = os.path.join(in_folder, second_file_name)

    danilo_in_folder = os.path.join(in_folder, "Danilo")
    if not os.path.exists(danilo_in_folder):
        try:
            os.mkdir(danilo_in_folder)
        except Exception as ex:
            logging.error(ex)
            # Abort
            raise Exception("Could not create input folder {0}".format(danilo_in_folder))

    move_files(csv_file_list, danilo_in_folder)

    csv_file_list = get_csv_files(danilo_in_folder)

    if not os.path.isfile(second_input_file) or len(csv_file_list) == 0:
        logger.info("Not all files necessary found. Aborting.")
        return

    inventory_dict = dict()
    for file in csv_file_list:
        read_inventory_file(file, inventory_dict)

    second_file_dict, header_row = read_second_file(second_input_file)

    header_row.append("stock")
    header_row.append("warehouse_id")

    for key in inventory_dict:
        if key in second_file_dict:
            # Append stock and hard-coded warehouse id
            second_file_dict[key] += [inventory_dict[key],"11"]

    out_file = os.path.join(out_folder, second_file_name)
    processed_file = os.path.join(processed_folder, second_file_name)

    write_csv(out_file, header_row, second_file_dict)

    move_files(csv_file_list, processed_folder)

    if os.path.exists(processed_file):
        os.remove(processed_file)

    shutil.move(second_input_file, processed_folder)


def main():
    global in_folder, out_folder, processed_folder, error_folder, ref_folder

    # data_root = r"/home/holger/git/thelen/data/"
    data_root = r"/ftproot/"
    # data_root = r"c:/temp/thelen/"

    project_folder = os.path.join(data_root, "Matching_Inventory_All")

    # setup sub folder paths
    source_folder = os.path.join(data_root, "Danilo_Bestand", "inventory_all")
    in_folder = os.path.join(project_folder, "in")
    out_folder = os.path.join(project_folder, "out")
    processed_folder = os.path.join(project_folder, "processed")
    error_folder = os.path.join(project_folder, "error")
    log_folder = os.path.join(project_folder, "log")
    ref_folder = os.path.join(project_folder, "ref")

    log_file = os.path.join(log_folder, 'process_inventory_all-' + time.strftime("%Y%m%d-%H%M%S") + '.log')

    setup_logging(log_file)

    try:
        process(source_folder)
    except Exception as ex:
        logging.exception(ex)

    teardown_logging()

    print("Done.")


if __name__ == "__main__":
    main()

