# -*- coding: utf-8 -*-
r"""Various constants and genome resources used in Consenrich.
"""

import logging
import os
from typing import List, Optional

logging.basicConfig(level=logging.INFO,
                     format='%(asctime)s - %(module)s.%(funcName)s -  %(levelname)s - %(message)s')
logging.basicConfig(level=logging.WARNING,
                    format='%(asctime)s - %(module)s.%(funcName)s -  %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

EFFECTIVE_GENOME_SIZES = {
    "hg19": {
        50: 2685511454,
        75: 2736124898,
        100: 2776919708,
        150: 2827436883,
        200: 2855463800,
        250: 2855044784,
    },
    "hg38": {
        50: 2701495711,
        75: 2747877702,
        100: 2805636231,
        150: 2862010428,
        200: 2887553103,
        250: 2898802627,
    },
    "t2t": {
        50: 2725240337,
        75: 2786136059,
        100: 2814334875,
        150: 2931551487,
        200: 2936403235,
        250: 2960856300,
    },
    "mm10": {
        50: 2308125299,
        75: 2407883243,
        100: 2467481008,
        150: 2494787038,
        200: 2520868989,
        250: 2538590322,
    },
    "mm39": {
        50: 2309746861,
        75: 2410055689,
        100: 2468088461,
        150: 2495461690,
        200: 2521902382,
        250: 2538633971,
    },
    "dm3": {
        50: 130428510,
        75: 135004387,
        100: 139647132,
        150: 144307658,
        200: 148523810,
        250: 151901455,
    },
    "dm6": {
        50: 125464678,
        75: 127324557,
        100: 129789773,
        150: 129940985,
        200: 132508963,
        250: 132900923,
    },
    "ce11": {
        50: 95159402,
        75: 96945370,
        100: 98259898,
        150: 98721103,
        200: 98672558,
        250: 101271756,
    }
}

def resolveGenomeName(genome: str) -> str:
    r"""Standardize the genome name for consistency
    :param genome: Name of the genome. See :class:`consenrich.core.genomeParams`.
    :type genome: str
    :return: Standardized genome name.
    :rtype: str
    :raises ValueError: If the genome is not recognized.
    """
    genome_ = genome.lower()
    if genome_ in ['hg19', 'grch37']:
        return 'hg19'
    elif genome_ in ['hg38', 'grch38']:
        return 'hg38'
    elif genome_ in ['t2t', 'chm13', 't2t-chm13']:
        return 't2t'
    elif genome_ in ['mm10', 'grcm38']:
        return 'mm10'
    elif genome_ in ['mm39', 'grcm39']:
        return 'mm39'
    elif genome_ in ['dm3']:
        return 'dm3'
    elif genome_ in ['dm6']:
        return 'dm6'
    elif genome_ in ['ce10','ws220']:
        return 'ce10'
    elif genome_ in ['ce11', 'wbcel235']:
        return 'ce11'
    raise ValueError(f"Genome {genome} is not recognized. Please provide a valid genome name or manually specify resources")


def getEffectiveGenomeSize(genome: str, readLength: int) -> int:
    r"""Get the effective genome size for a given genome and read length.

    :param genome: Name of the genome. See :func:`consenrich.constants.resolveGenomeName` and :class:`consenrich.core.genomeParams`.
    :type genome: str
    :param readLength: Length of the reads. See :func:`consenrich.core.getReadLength`.
    :type readLength: int
    :raises ValueError: If the genome is not recognized or if the read length is not available for the genome.
    :return: Effective genome size in base pairs.
    :rtype: int
    """

    global EFFECTIVE_GENOME_SIZES
    genome_: str = resolveGenomeName(genome)
    if genome_ in EFFECTIVE_GENOME_SIZES:
        if readLength not in EFFECTIVE_GENOME_SIZES[genome_]:
            nearestReadLength: int = int(min(EFFECTIVE_GENOME_SIZES[genome_].keys(), key=lambda x: abs(x - readLength)))
            return EFFECTIVE_GENOME_SIZES[genome_][nearestReadLength]
        return EFFECTIVE_GENOME_SIZES[genome_][readLength]
    raise ValueError(f"Defaults not available for {genome}")


def getGenomeResourceFile(genome: str, fileType: str, dir_: str='data'):
    r"""Get the path to a genome resource file.

    :param genome: the genome assembly. See :func:`consenrich.constants.resolveGenomeName` and :class:`consenrich.core.genomeParams`.
    :type genome: str
    :param fileType: One of 'sizes', 'blacklist', 'sparse'.
    :type fileType: str
    :return: Path to the resource file.
    :rtype: str
    :raises ValueError: If not a sizes, blacklist, or sparse file.
    :raises FileNotFoundError: If the resource file does not exist.
    """
    if fileType.lower() in ['sizes']:
        fileName = f"{genome}.sizes"
    elif fileType.lower() in ['blacklist']:
        fileName = f"{genome}_blacklist.bed"
    elif fileType.lower() in ['sparse']:
        fileName = f"{genome}_sparse.bed"
    filePath = os.path.join(os.path.dirname(__file__), os.path.join(dir_, fileName))
    if not os.path.exists(filePath):
        raise FileNotFoundError(f"Resource file {filePath} does not exist.")
    return filePath