#!/usr/bin/env python

# Extracts "block" features based on existing features

import argparse
import logging
import pandas as pd
import csv
import gc
import numpy as np

from common.configuration import ConfigurationHandler
from common.workspace import WorkspaceHandler

logger = logging.getLogger('pyccflex')
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
logger.addHandler(ch)

if __name__ == '__main__':

    logger.info("\n#### Running: {}".format(__file__))

    # Parse input parameters
    parser = argparse.ArgumentParser()

    parser.add_argument("input_file",
                        help="Path to a feature file", type=str)
    parser.add_argument("output_file",
                        help="Path to output csv file", type=str)
    parser.add_argument("feature_name",
                        help="The name of feature to create", type=str)
    parser.add_argument("--feature_start", nargs='+', type=str,
                        help="The name of feature to start a block", required=True)
    parser.add_argument("--feature_end", nargs='+', type=str,
                        help="The name of feature to end a block", required=True)
    parser.add_argument("--forbidding_features", nargs='+', type=str, required=False, default=[],
                        help="If any of these features are greater than zero the feature is set to zero")
    parser.add_argument("--locations_config", help="Path to locations configuration file",
                        type=str, required=False, default="./locations.json")
    parser.add_argument("--files_format_config", help="Path to files format configuration file",
                        type=str, required=False, default="./files_format.json")
    parser.add_argument("--add_contents", help="Shall the content of the line be added to output?",
                        default=False, action='store_true')

    args = vars(parser.parse_args())
    logger.info("Run parameters: {}".format(str(args)))

    locations_file_path = args['locations_config']
    files_format_file_path = args['files_format_config']
    input_file = args['input_file']
    output_file = args['output_file']
    add_contents = args['add_contents']
    feature_name = args['feature_name']
    feature_start = args['feature_start']
    feature_end = args['feature_end']
    forbidding_features = args['forbidding_features']

    try:
        locations_config = ConfigurationHandler(locations_file_path)
    except Exception as e:
        logger.error("Couldn't load configuration file {}".format(locations_file_path))
        exit(1)

    try:
        files_format_config = ConfigurationHandler(files_format_file_path)
    except Exception as e:
        logger.error("Couldn't load configuration file {}".format(files_format_file_path))
        exit(1)
    csv_separator = files_format_config.get("csv_sep", ",")

    workspace_dir_conf = locations_config.get('workspace_dir', None)
    workspace_dir_path = workspace_dir_conf.get("path", "")
    workspace_dir = WorkspaceHandler(workspace_dir_path)

    logger.info(">>> Loading input the file {}".format(input_file))

    input_file_path = workspace_dir.get_processing_file_path(input_file)
    output_file_path = workspace_dir.get_processing_file_path(output_file)

    with open(input_file_path, "r", newline='', encoding="utf-8") as in_csv:
        reader = csv.DictReader(in_csv, delimiter=csv_separator, quotechar='"', quoting=csv.QUOTE_NONNUMERIC)
        with open(output_file_path, "w", newline='', encoding="utf-8") as out_csv:
            writer = csv.writer(out_csv, delimiter=csv_separator, quotechar='"', quoting=csv.QUOTE_NONNUMERIC)

            header_row = ['id', feature_name]
            if add_contents:
                header_row.append('contents')
            writer.writerow(header_row)

            last_filename = None
            inside = 0
            for row in reader:
                filename = row['id'].split(":")[0]

                feature_value = 0
                forbidden = np.sum([int(row.get(forb, 0)) for forb in forbidding_features]) > 0
                if not forbidden:
                    start = np.sum([int(row.get(fs, 0)) for fs in feature_start]) > 0
                    end = np.sum([int(row.get(fe, 0)) for fe in feature_end]) > 0

                    if start and end:
                        label = 'start_end'
                    elif start:
                        label = 'start'
                    elif end:
                        label = 'end'
                    else:
                        label = 'ignore'


                    if label == 'start_end':
                        feature_value = 1
                    else:
                        if last_filename != filename:
                            last_filename = filename
                            inside = 0

                        if label == 'start':
                            feature_value = 1
                            inside += 1
                        elif label == 'end' and inside > 0:
                            feature_value = 1
                            inside = 0
                            # inside -= 1   # this line is when we want to catch nested blocks; which is a problem
                        else:
                            if inside > 0:
                                feature_value = 1

                out_row = [row['id'], feature_value]
                if add_contents:
                    out_row.append(row['contents'])
                writer.writerow(out_row)

    logger.info(">>> Output saved to the file {}".format(output_file))
