from __future__ import print_function
import os
import sys
import subprocess
import tempfile
import logging
from six.moves import urllib
from six.moves import copyreg
from . import scripts
from .cbedtools import (Interval, IntervalFile, overlap, Attributes,
                        MalformedBedLineError, IntervalIterator)
from . import contrib
from .helpers import (get_tempdir, set_tempdir, cleanup, find_tagged,
                      set_bedtools_path, chromsizes, get_chromsizes_from_ucsc,
                      chromsizes_to_file, create_interval_from_list)
from . import helpers
from .bedtool import BedTool
from . import genome_registry
from . import stats
from .__main__ import main
from .version import __version__
from .filenames import data_dir, example_filename, list_example_files
from .bedtool import example_bedtool

from . import settings
from .logger import logger, ch

example_files = ['a.bed.', 'b.bed', 'test.fa', 'a.bam']


def debug_mode(x):
    """
    Enable debug mode.

    Use debug_mode(True) to show debug log events in the console and to save
    calling info in BedTool objects, and turn it off again with
    debug_mode(False).

    Note that `pybedtools.KEEP_TEMPFILES` will be set as well, so you will need
    to clean up the tempfile directory manually after using debug mode.
    """
    if x:
        logger.setLevel(logging.DEBUG)
        ch.setLevel(logging.DEBUG)
        _DEBUG = True
        KEEP_TEMPFILES = True
        logger.info(
            'Debug mode enabled.  You may also want to set '
            'pybedtools.KEEP_TEMPFILES=True to prevent automatic deletion '
            'of files upon exit.')
    else:
        logger.setLevel(logging.INFO)
        ch.setLevel(logging.INFO)
        _DEBUG = False
        KEEP_TEMPFILES = False
        logger.info('Debug mode disabled')


def check_for_bedtools(program_to_check="intersectBed", force_check=False):
    """
    For backwards compatibility; please use helpers._check_for_bedtools()
    """
    return helpers._check_for_bedtools(program_to_check, force_check)


# Allow Interval objects to be pickled -- required if you want to pass them
# across process boundaries
def interval_constructor(fields):
    return create_interval_from_list(list(fields))


def interval_reducer(interval):
    return interval_constructor, (tuple(interval.fields), )

copyreg.pickle(Interval, interval_reducer, interval_constructor)


def load_path_config(fn):
    """
    You can use a config file to specify installation paths of various programs
    used by pybedtools.  This can be useful for testing, or using different
    versions of programs.

    `fn` is a config file with the following format.  If an entry is blank,
    then assume it's already on the path. All items must be lowercase::

        [paths]
        bedtools=/tools/BEDTools/bin
        r=
        tabix=
        bgzip=

    You only need to specify paths you need to change, so this is a valid file
    that will only specify the path to use for R::

        [paths]
        r=/usr/bin/R-dev

    If `fn` is not a string, then assume it is a dictionary of (program,
    paths). This is used primarily for testing.
    """
    setters = dict(
        bedtools=helpers.set_bedtools_path,
        r=helpers.set_R_path,
        tabix=helpers.set_tabix_path,
        bgzip=helpers.set_bgzip_path)

    if isinstance(fn, dict):
        for prog, setter in list(setters.items()):
            try:
                path = fn[prog]
                setter(path)
            except KeyError:
                pass

    if isinstance(fn, str):
        from six.moves import configparser
        c = configparser.SafeConfigParser()
        c.read(fn)
        if c.sections() != ['paths']:
            raise ValueError("Invalid path config -- must have "
                             "only one section, [paths].")
        for prog, setter in list(setters.items()):
            try:
                path = c.get('paths', prog)
                setter(path)

            except configparser.NoOptionError:
                pass
