#!/usr/bin/env python3

import os
import shutil
import pickle
import time
import logging
import sys


def validate_directories(paths, should_create=False):
    for path in paths:
        if not os.path.isdir(path):
            if should_create:
                if not os.path.isfile(path):
                    os.makedirs(path)
                else:
                    raise FileExistsError(f"A file with the name '{path}' already exists.")
            else:
                raise FileNotFoundError(f"'{path}' does not exist or is not a directory.")


def copy_directory_content(source_dir, destination_dir):
    validate_directories([source_dir])
    validate_directories([destination_dir], should_create=True)

    for item in os.listdir(source_dir):
        source_item = os.path.join(source_dir, item)
        destination_item = os.path.join(destination_dir, item)

        # copies all files with the extension ".fastq"
        # does not copy if file already exists
        if (
            not os.path.exists(destination_item)
            and os.path.isfile(source_item)
            and source_item.endswith(".fastq")
        ):
            shutil.copy2(source_item, destination_item)

    print(f"Contents of '{source_dir}' copied to '{destination_dir}' successfully.")


def change_working_directory(path, logger):
    try:
        # Change the current working directory
        os.chdir(path)
        logger.info(f"Current working directory updated to '{path}'.")
    except Exception as e:
        logger.error(f"An error occurred: {e}")


def get_new_files_info(directory, cookie):
    def get_last_run_timestamp(cookie):
        try:
            with open(cookie, "rb") as f:
                timestamp = pickle.load(f)
        except FileNotFoundError:
            return 0
        return timestamp

    def update_last_run_timestamp(cookie, timestamp):
        with open(cookie, "wb") as f:
            pickle.dump(timestamp, f)

    last_run_timestamp = get_last_run_timestamp(cookie)
    current_timestamp = time.time()

    update_last_run_timestamp(cookie, current_timestamp)

    files = os.listdir(directory)

    for filename in files:
        filepath = os.path.join(directory, filename)
        # Get the creation time of the file
        creation_time = os.path.getctime(filepath)
        # Check if the file was created since the last run
        if last_run_timestamp < creation_time:
            file_size = os.path.getsize(filepath)
            yield filename, file_size


def build_logger(log_file):
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    formatter = logging.Formatter("%(message)s")

    # logging to both std
    stdout_handler = logging.StreamHandler(sys.stdout)
    stdout_handler.setLevel(logging.DEBUG)
    stdout_handler.setFormatter(formatter)

    # concurrently, also log to output file
    file_handler = logging.FileHandler(log_file)
    file_handler.setLevel(logging.DEBUG)
    file_handler.setFormatter(formatter)

    logger.addHandler(file_handler)
    logger.addHandler(stdout_handler)

    return logger


def combine_files(file1_path, file2_path, output_file_path):
    with open(file1_path, "rb") as file1, open(file2_path, "rb") as file2, open(
        output_file_path, "wb"
    ) as output_file:
        shutil.copyfileobj(file1, output_file)
        shutil.copyfileobj(file2, output_file)


def preserve_first_n_tokens(filename, separator, n):
    basename = filename.split(".")[0]
    tokens = basename.split(separator)
    preserved_tokens = tokens[:n]
    preserved_file_name = separator.join(preserved_tokens)
    return preserved_file_name
