#!/usr/bin/env python

__author__ = 'holger.knust'

import codecs
import csv
import os
import shutil


def read_item_no_lookup(ref_path):
    ref_dict = {}

    header_read = False
    full_ref_path = os.path.join(ref_path, "Referenz_Matching_ID.csv")
    with codecs.open(full_ref_path, "rb", encoding='utf-8') as f:
        #dialect = csv.Sniffer().sniff(f.read(1024), delimiters=";")
        #f.seek(0)

        reader = csv.reader(f, delimiter=';')
        for row in reader:
            if header_read:
                ref_dict[row[1]] = row[0]
            else:
                header_read = True
    return ref_dict

def read_ean_lookup(ref_path):
    ref_dict = {}

    header_row = []
    header_read = False
    full_ref_path = os.path.join(ref_path, "Referenz_Matching_EAN.csv")
    with codecs.open(full_ref_path, "rb", encoding='utf-8') as f:
        #dialect = csv.Sniffer().sniff(f.read(1024), delimiters=";")
        #f.seek(0)

        reader = csv.reader(f, delimiter=';')
        ean_col_no = -1
        for row in reader:
            if header_read:
                ean = row.pop(ean_col_no)
                ref_dict[ean] = row
            else:
                header_row = row
                ean_col_no = header_row.index("EAN")
                id_col_no = header_row.index("ItemID")
                header_row.pop(ean_col_no)
                header_row.pop(id_col_no)
                header_read = True

    return ref_dict, header_row

def read_price_lookup(ref_file_path):
    ref_dict = {}

    header_row = []
    header_read = False
    with codecs.open(ref_file_path, "r", encoding='utf-8') as f:
        #dialect = csv.Sniffer().sniff(f.read(1024), delimiters=";")
        #f.seek(0)

        reader = csv.reader(f, delimiter=';')
        id_col_no = -1
        for row in reader:
            if header_read:
                ean = row.pop(id_col_no)
                ref_dict[ean] = row
            else:
                header_row = row

                if "EAN" in header_row:
                    id_col_no = header_row.index("EAN")
                elif "Artikel / Farb Nummer" in header_row:
                    id_col_no = header_row.index("Artikel / Farb Nummer")
                elif "Artikelnummer" in header_row:
                    id_col_no = header_row.index("Artikelnummer")
                elif "ItemId" in header_row:
                    id_col_no = header_row.index("ItemID")
                header_row.pop(id_col_no)
                header_read = True

    return ref_dict, header_row


def convert_item_no(in_file, out_file, ref_dict):
    header_read = False
    no_index = -1

    with codecs.open(in_file, "r", encoding='utf-8') as f, codecs.open(out_file, "w", encoding='utf-8') as of:
        #dialect = csv.Sniffer().sniff(f.read(1024), delimiters=";")
        #f.seek(0)

        reader = csv.reader(f, delimiter=';')
        writer = csv.writer(of, delimiter=';')
        for row in reader:
            if any(row):
                if header_read:
                    item_id = "ERROR"
                    if row[no_index] in ref_dict:
                        item_id = ref_dict[row[no_index]]
                    row.insert(0, item_id)
                else:
                    header_read = True
                    no_index = row.index('ItemNo')
                    row.insert(0, 'ItemId')
                writer.writerow(row)

def convert_ean(in_file, out_file, ref_dict, header_row):
    header_read = False
    no_index = -1

    with codecs.open(in_file, "r", encoding='utf-8') as f, codecs.open(out_file, "w", encoding='utf-8') as of:
        #dialect = csv.Sniffer().sniff(in_file.read(1024), delimiters=";")
        #in_file.seek(0)
        reader = csv.reader(f, delimiter=';')
        writer = csv.writer(of, delimiter=';')
        for row in reader:
            if any(row):
                if header_read:
                    item_id = "ERROR"
                    row2 = []
                    ean = row[no_index]
                    if len(ean) == 14:
                        ean = ean[1:]
                    if ean in ref_dict:
                        row2 = ref_dict[ean]
                        item_id = row2.pop(0)
                    row.insert(0, item_id)
                    if len(row2) > 1:
                        start_pos = len(row) + 1
                        for col in row2:
                            row.insert(start_pos, col)
                            start_pos = start_pos + 1
                else:
                    header_read = True
                    no_index = row.index('EAN')
                    row.insert(0, 'ItemId')
                    start_pos = len(row) + 1
                    for col in header_row:
                        row.insert(start_pos, col)
                        start_pos = start_pos + 1

                writer.writerow(row)

def convert_price(in_file, out_file, ref_dict, header_row):
    header_read = False
    no_index = -1
    price_index_nos = []

    with codecs.open(in_file, "r", encoding='utf-8') as f, codecs.open(out_file, "w", encoding='utf-8') as of:
        #dialect = csv.Sniffer().sniff(f.read(1024), delimiters=";")
        #f.seek(0)

        reader = csv.reader(f, delimiter=';')
        writer = csv.writer(of, delimiter=';')
        for row in reader:
            if any(row):
                if header_read:
                    row2 = []
                    curr_item_id = row[no_index]
                    if curr_item_id in ref_dict:
                        row2 = ref_dict[curr_item_id]
                        # item_id = row2.pop(0)
                    start_pos = len(row) + 1
                    if len(row2) > 1:
                        for i in price_index_nos:
                          row.insert(start_pos, row2[i])
                          start_pos = start_pos + 1
                    else:
                        for i in price_index_nos:
                          row.insert(start_pos, "ERROR")
                          start_pos = start_pos + 1
                else:
                    header_read = True
                    in_header_row = row
                    if "Artikelnummer" in in_header_row:
                        no_index = row.index("Artikelnummer")
                    elif "ItemId" in in_header_row:
                        no_index = row.index("ItemId")
                    else:
                        raise Exception("No id found")

                    start_pos = len(row) + 1

                    # get price index columns from ref and add to output
                    for i in range(len(header_row)):
                        if header_row[i].lower().find("preis") > -1:
                            row.insert(start_pos, header_row[i])
                            start_pos = start_pos + 1
                            price_index_nos.append(i)

                writer.writerow(row)

def process_item_no(data_root):
    path_ref = os.path.join(data_root, "ref")
    path_in = os.path.join(data_root, "in")
    path_out = os.path.join(data_root, "out")
    path_proc = os.path.join(data_root, "processed")
    path_err = os.path.join(data_root, "error")

    files = os.listdir(path_in)
    num_files = len(files)

    print("Found {0} files...".format(num_files))

    if num_files == 0:
        return

    ref_dict = read_item_no_lookup(path_ref)

    for f in files:
        in_file = os.path.join(path_in, f)
        out_file = os.path.join(path_out, f)
        proc_file = os.path.join(path_proc, f)
        err_file = os.path.join(path_err, f)

        if os.path.isfile(in_file):
            print("Converting {0} to {1}...".format(in_file, out_file))
            try:
                convert_item_no(in_file, out_file, ref_dict)
                shutil.move(in_file, proc_file)
            except Exception as e:
                print(e)
                shutil.move(in_file, err_file)

def process_ean(data_root):
    path_ref = os.path.join(data_root, "ref")
    path_in = os.path.join(data_root, "in")
    path_out = os.path.join(data_root, "out")
    path_proc = os.path.join(data_root, "processed")
    path_err = os.path.join(data_root, "error")

    files = os.listdir(path_in)
    num_files = len(files)

    print("Found {0} files...".format(num_files))

    if num_files == 0:
        return

    ref_dict, header_row = read_ean_lookup(path_ref)

    for f in files:
        in_file = os.path.join(path_in, f)
        out_file = os.path.join(path_out, f)
        proc_file = os.path.join(path_proc, f)
        err_file = os.path.join(path_err, f)

        if os.path.isfile(in_file):
            print("Converting {0} to {1}...".format(in_file, out_file))
            try:
                convert_ean(in_file, out_file, ref_dict, header_row)
                shutil.move(in_file, proc_file)
            except Exception as e:
                print(e)
                shutil.move(in_file, err_file)

def process_pricing(data_root):
    path_ref = os.path.join(data_root, "in")
    path_in = os.path.join(data_root, "in")
    path_out = os.path.join(data_root, "out")
    path_proc = os.path.join(data_root, "processed")
    path_err = os.path.join(data_root, "error")

    files = os.listdir(path_in)
    num_files = len(files)

    print("Found {0} files...".format(num_files))

    if num_files == 0:
        return

    if num_files % 2 != 0:
        print("The number of files {0} should be even...".format(num_files))

    for f in files:
        base_file_name = os.path.basename(f)
        file_name_parts = base_file_name.split('.')

        if len(file_name_parts) == 0:
            print("{0} does not contain a .".format(base_file_name))
            continue

        file_name = file_name_parts[:-1]
        file_ext = file_name_parts[-1:]

        if len(file_name) == 0:
            continue

        file_number = file_name[0][-1:]

        # process files ending in 1 only
        if file_number != '1':
            continue

        file_name_root = file_name[0]
        print("File name root {0}".format(file_name_root))

        # generate matching price file name
        price_file_name = file_name_root[:-1] + '2.' + file_ext[0]

        in_file = os.path.join(path_in, f)
        out_file = os.path.join(path_out, f)
        proc_file = os.path.join(path_proc, f)
        err_file = os.path.join(path_err, f)
        ref_file = os.path.join(path_ref, price_file_name)
        proc_ref_file = os.path.join(path_proc, price_file_name)
        err_ref_file = os.path.join(path_err, price_file_name)

        if not os.path.isfile(ref_file):
            print("Price file {0} not found".format(ref_file))
            continue


        if os.path.isfile(in_file):
            print("Looking up prices for {0} in {1}...".format(in_file, price_file_name))
            try:
                ref_dict, header_row = read_price_lookup(ref_file)
                convert_price(in_file, out_file, ref_dict, header_row)
                shutil.move(in_file, proc_file)
                shutil.move(ref_file, proc_ref_file)
            except Exception as e:
                print(e)
                shutil.move(in_file, err_file)
                shutil.move(ref_file, err_ref_file)

def main():
    data_root = r"/ftproot/"
    #data_root = r"/ftproot/"
	
    item_no_data_root = os.path.join(data_root, "Matching_NO")
    ean_data_root = os.path.join(data_root, "Matching_EAN")
    price_data_root = os.path.join(data_root, "Matching_Allg")

    process_item_no(item_no_data_root)
    process_ean(ean_data_root)
    process_pricing(price_data_root)

    print("Done.")


if __name__ == "__main__":
    main()
