# -*- coding: utf-8 -*-

import logging
import os

import numpy as np

import pkg_resources

from sqlalchemy import Column, Float, PickleType, String, Text, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

logging.basicConfig(level=logging.getLevelName(
    os.getenv('LOG_LEVEL', 'WARNING')))
LOGGER = logging.getLogger(__name__)

DATABASE_FILE = pkg_resources.resource_filename(__name__, "data.db")
ENGINE = create_engine('sqlite:///' + DATABASE_FILE, echo=False)
BASE = declarative_base()
SESSION = sessionmaker(bind=ENGINE)


class Field(BASE):
    """Sky field in HELP"""

    __tablename__ = 'fields'

    name = Column(String, primary_key=True)
    short_id = Column(String)
    footprint = Column(PickleType)

    def __init__(self, name, short_id, footprint):
        """Create a field.

        Parameters
        ----------
        name : string
            Name of the field.
        short_id : string
            Three letter identifiers of the field.
        footprint : pymoc.MOC
            Multi-order coverage map representing the footprint of the field.

        """
        self.name = name
        self.short_id = short_id
        self.footprint = footprint


class Filter(BASE):
    """Photometric filters

    This class represents a photometric filter in HELP database. A filter has
    these attributes:

    - filter_id: A unique identifier.  It is used in naming the column in HELP
      catalogues.
    - description: A human readable short description of the filter.
    - band_name: A standard representation for the band (e.g. “g” for a g band
      filter).
    - facility: The name of the observatory or telescope.
    - instrument: The name of the instrument.
    - mean_wavelength: The mean wavelength in Angstrom.
    - min_wavelength: First wavelength (in Angstrom) with a transmission at
      least 1% of the maximum transmission.
    - max_wavelength: Last wavelength (in Angstrom) with a transmission at
      least 1% of the maximum transmission.
    - att_ebv: The ratio between the attenuation in the filter and the E(B-V)
      color excess. It is computed using the Fitzpatrick (1999) extinction
      curve assuming a flat emission spectrum.
    - response: The filter response curve as a two axis numpy array with the
      wavelength in Angstrom in the first axis and the energetic transmission
      in the second one.
    - notes: Notes from the HELP project.

    """

    __tablename__ = 'filters'

    filter_id = Column(String, primary_key=True)
    description = Column(String)
    band_name = Column(String)
    facility = Column(String)
    instrument = Column(String)
    mean_wavelength = Column(Float)
    min_wavelength = Column(Float)
    max_wavelength = Column(Float)
    att_ebv = Column(Float)
    response = Column(PickleType)
    notes = Column(Text)

    def __init__(self, filter_id, description, band_name, facility, instrument,
                 mean_wavelength, min_wavelength, max_wavelength, att_ebv,
                 response, notes):
        """Create a photometric filter.

        Parameters
        ----------
        filter_id: string
            Unique identfier.
        description: string
            Human readable short description of the filter.
        band_name: string
            Standard representation of the band.
        facility: string
            Observatory or telescope.
        instrument: string
            Instrument name.
        mean_wavelength: float
            Mean wavelength of the filter in Angstrom.
        min_wavelength: float
            Minimal wavelength with at least 1% of maximum transmission in
            Angstrom.
        max_wavelength: float
            Last wavelength with at least 1% of maximum transmission in
            Angstrom.
        att_ebv: float
            Ratio between the attenuation in the filter and the E(B-V) color
            excess.
        response: numpy array of float
            Response curve of the filter, response[0] is the wavelength in
            Angstrom and transmission_curve[1] is the energetic transmission.
        notes: string
            Notes about the filter is any.
        """
        self.filter_id = filter_id
        self.description = description
        self.band_name = band_name
        self.facility = facility
        self.instrument = instrument
        self.mean_wavelength = mean_wavelength
        self.min_wavelength = min_wavelength
        self.max_wavelength = max_wavelength
        self.att_ebv = att_ebv
        self.response = response
        self.notes = notes


class Database(object):
    """Object giving access to the module database.

    This object can be used in a context manager.
    """

    def __init__(self, writable=False):
        """Create a connection manager to the module database

        writable : boolean
            If true, the users will have write access to the database
            provided they can write the sqlite file. By default, it's
            false.
        """
        self.session = SESSION()
        self.is_writable = writable
        LOGGER.debug("Initialising the database.")

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()

    def upgrade_base(self):
        """Upgrade the table schemas in the database."""
        if self.is_writable:
            BASE.metadata.create_all(ENGINE)
        else:
            raise Exception("The database is not writable.")

    def close(self):
        """Close the connection to the database."""
        self.session.close_all()
        LOGGER.debug("Closing the database.")


def get_field(*args):
    """Retrieves HELP fields information.

    This function retrieves information about HELP fields in the database. The
    return depends on the arguments.

    - If there is only one argument, the function returns the field
      corresponding to the name given in argument. If there is no field with
      that name, None is returned.
    - If there are several arguments, the function return the list of fields
      corresponding to the given names. If none of the given names correspond
      to actual fields, an empty list is returned.
    - If no argument is given, the function returns the list of all the HELP
      fields.

    Each field is returned as a Field object with these attributes:

    - name: the full name of the field;
    - short_id: its three letters identifier;
    - footprint: its footprint as a pymoc.MOC object.

    Parameters
    ----------
    *args : str
        Name or names (several arguments, not a list of names) of the fields.

    Returns
    -------
    Field or list of fields
        If exactly one argument is given returns a Field (or None) else returns
        a list of fields.

    """

    with Database() as d:
        if len(args) == 0:
            return d.session.query(Field).all()
        elif len(args) == 1:
            return d.session.query(Field).get(args[0])
        else:
            return d.session.query(Field).filter(
                Field.name.in_(args)).all()


def get_filters(*args):
    """Retrieves HELP photometric filters information.

    This function retrieves information about the photometric filters used in
    HELP.  The return depends on the arguments.

    - If there is only one argument, the function returns the filter
      corresponding to the filter ID given in argument. If there is no filter
      with that ID, None is returned.
    - If there are several arguments, the function return the list of filters
      corresponding to the given IDs. If none of the given IDs correspond to
      actual filters, an empty list is returned.
    - If no argument is given, the function returns the list of all the filters
      in the database.

    Parameters
    ----------
    *args : str
        ID or IDs (several arguments, not a list) of the filters.

    Returns
    -------
    Filter or list of Filters
        If exactly one argument is given returns a Filter (or None) else
        returns a list of filters.

    """

    with Database() as d:
        if len(args) == 0:
            return d.session.query(Filter).all()
        elif len(args) == 1:
            return d.session.query(Filter).get(args[0])
        else:
            return d.session.query(Filter).filter(
                Filter.filter_id.in_(args)).all()

# -*- coding: utf-8 -*-

import logging
import os

import numpy as np

import pkg_resources

from sqlalchemy import Column, Float, PickleType, String, Text, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

logging.basicConfig(level=logging.getLevelName(
    os.getenv('LOG_LEVEL', 'WARNING')))
LOGGER = logging.getLogger(__name__)

DATABASE_FILE = pkg_resources.resource_filename(__name__, "data.db")
ENGINE = create_engine('sqlite:///' + DATABASE_FILE, echo=False)
BASE = declarative_base()
SESSION = sessionmaker(bind=ENGINE)


class Field(BASE):
    """Sky field in HELP"""

    __tablename__ = 'fields'

    name = Column(String, primary_key=True)
    short_id = Column(String)
    footprint = Column(PickleType)

    def __init__(self, name, short_id, footprint):
        """Create a field.

        Parameters
        ----------
        name : string
            Name of the field.
        short_id : string
            Three letter identifiers of the field.
        footprint : pymoc.MOC
            Multi-order coverage map representing the footprint of the field.

        """
        self.name = name
        self.short_id = short_id
        self.footprint = footprint


class Filter(BASE):
    """Photometric filters

    This class represents a photometric filter in HELP database. A filter has
    these attributes:

    - filter_id: A unique identifier.  It is used in naming the column in HELP
      catalogues.
    - description: A human readable short description of the filter.
    - band_name: A standard representation for the band (e.g. “g” for a g band
      filter).
    - facility: The name of the observatory or telescope.
    - instrument: The name of the instrument.
    - mean_wavelength: The mean wavelength in Angstrom.
    - min_wavelength: First wavelength (in Angstrom) with a transmission at
      least 1% of the maximum transmission.
    - max_wavelength: Last wavelength (in Angstrom) with a transmission at
      least 1% of the maximum transmission.
    - att_ebv: The ratio between the attenuation in the filter and the E(B-V)
      color excess. It is computed using the Fitzpatrick (1999) extinction
      curve assuming a flat emission spectrum.
    - response: The filter response curve as a two axis numpy array with the
      wavelength in Angstrom in the first axis and the energetic transmission
      in the second one.
    - notes: Notes from the HELP project.

    """

    __tablename__ = 'filters'

    filter_id = Column(String, primary_key=True)
    description = Column(String)
    band_name = Column(String)
    facility = Column(String)
    instrument = Column(String)
    mean_wavelength = Column(Float)
    min_wavelength = Column(Float)
    max_wavelength = Column(Float)
    att_ebv = Column(Float)
    response = Column(PickleType)
    notes = Column(Text)

    def __init__(self, filter_id, description, band_name, facility, instrument,
                 mean_wavelength, min_wavelength, max_wavelength, att_ebv,
                 response, notes):
        """Create a photometric filter.

        Parameters
        ----------
        filter_id: string
            Unique identfier.
        description: string
            Human readable short description of the filter.
        band_name: string
            Standard representation of the band.
        facility: string
            Observatory or telescope.
        instrument: string
            Instrument name.
        mean_wavelength: float
            Mean wavelength of the filter in Angstrom.
        min_wavelength: float
            Minimal wavelength with at least 1% of maximum transmission in
            Angstrom.
        max_wavelength: float
            Last wavelength with at least 1% of maximum transmission in
            Angstrom.
        att_ebv: float
            Ratio between the attenuation in the filter and the E(B-V) color
            excess.
        response: numpy array of float
            Response curve of the filter, response[0] is the wavelength in
            Angstrom and transmission_curve[1] is the energetic transmission.
        notes: string
            Notes about the filter is any.
        """
        self.filter_id = filter_id
        self.description = description
        self.band_name = band_name
        self.facility = facility
        self.instrument = instrument
        self.mean_wavelength = mean_wavelength
        self.min_wavelength = min_wavelength
        self.max_wavelength = max_wavelength
        self.att_ebv = att_ebv
        self.response = response
        self.notes = notes


class Database(object):
    """Object giving access to the module database.

    This object can be used in a context manager.
    """

    def __init__(self, writable=False):
        """Create a connection manager to the module database

        writable : boolean
            If true, the users will have write access to the database
            provided they can write the sqlite file. By default, it's
            false.
        """
        self.session = SESSION()
        self.is_writable = writable
        LOGGER.debug("Initialising the database.")

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()

    def upgrade_base(self):
        """Upgrade the table schemas in the database."""
        if self.is_writable:
            BASE.metadata.create_all(ENGINE)
        else:
            raise Exception("The database is not writable.")

    def close(self):
        """Close the connection to the database."""
        self.session.close_all()
        LOGGER.debug("Closing the database.")


def get_field(*args):
    """Retrieves HELP fields information.

    This function retrieves information about HELP fields in the database. The
    return depends on the arguments.

    - If there is only one argument, the function returns the field
      corresponding to the name given in argument. If there is no field with
      that name, None is returned.
    - If there are several arguments, the function return the list of fields
      corresponding to the given names. If none of the given names correspond
      to actual fields, an empty list is returned.
    - If no argument is given, the function returns the list of all the HELP
      fields.

    Each field is returned as a Field object with these attributes:

    - name: the full name of the field;
    - short_id: its three letters identifier;
    - footprint: its footprint as a pymoc.MOC object.

    Parameters
    ----------
    *args : str
        Name or names (several arguments, not a list of names) of the fields.

    Returns
    -------
    Field or list of fields
        If exactly one argument is given returns a Field (or None) else returns
        a list of fields.

    """

    with Database() as d:
        if len(args) == 0:
            return d.session.query(Field).all()
        elif len(args) == 1:
            return d.session.query(Field).get(args[0])
        else:
            return d.session.query(Field).filter(
                Field.name.in_(args)).all()


def get_filters(*args):
    """Retrieves HELP photometric filters information.

    This function retrieves information about the photometric filters used in
    HELP.  The return depends on the arguments.

    - If there is only one argument, the function returns the filter
      corresponding to the filter ID given in argument. If there is no filter
      with that ID, None is returned.
    - If there are several arguments, the function return the list of filters
      corresponding to the given IDs. If none of the given IDs correspond to
      actual filters, an empty list is returned.
    - If no argument is given, the function returns the list of all the filters
      in the database.

    Parameters
    ----------
    *args : str
        ID or IDs (several arguments, not a list) of the filters.

    Returns
    -------
    Filter or list of Filters
        If exactly one argument is given returns a Filter (or None) else
        returns a list of filters.

    """

    with Database() as d:
        if len(args) == 0:
            return d.session.query(Filter).all()
        elif len(args) == 1:
            return d.session.query(Filter).get(args[0])
        else:
            return d.session.query(Filter).filter(
                Filter.filter_id.in_(args)).all()

# -*- coding: utf-8 -*- Sky field in HELP Create a field.          Parameters         ----------         name : string             Name of the field.         short_id : string             Three letter identifiers of the field.         footprint : pymoc.MOC             Multi-order coverage map representing the footprint of the field. Photometric filters      This class represents a photometric filter in HELP database. A filter has     these attributes:      - filter_id: A unique identifier.  It is used in naming the column in HELP       catalogues.     - description: A human readable short description of the filter.     - band_name: A standard representation for the band (e.g. “g” for a g band       filter).     - facility: The name of the observatory or telescope.     - instrument: The name of the instrument.     - mean_wavelength: The mean wavelength in Angstrom.     - min_wavelength: First wavelength (in Angstrom) with a transmission at       least 1% of the maximum transmission.     - max_wavelength: Last wavelength (in Angstrom) with a transmission at       least 1% of the maximum transmission.     - att_ebv: The ratio between the attenuation in the filter and the E(B-V)       color excess. It is computed using the Fitzpatrick (1999) extinction       curve assuming a flat emission spectrum.     - response: The filter response curve as a two axis numpy array with the       wavelength in Angstrom in the first axis and the energetic transmission       in the second one.     - notes: Notes from the HELP project. Create a photometric filter.          Parameters         ----------         filter_id: string             Unique identfier.         description: string             Human readable short description of the filter.         band_name: string             Standard representation of the band.         facility: string             Observatory or telescope.         instrument: string             Instrument name.         mean_wavelength: float             Mean wavelength of the filter in Angstrom.         min_wavelength: float             Minimal wavelength with at least 1% of maximum transmission in             Angstrom.         max_wavelength: float             Last wavelength with at least 1% of maximum transmission in             Angstrom.         att_ebv: float             Ratio between the attenuation in the filter and the E(B-V) color             excess.         response: numpy array of float             Response curve of the filter, response[0] is the wavelength in             Angstrom and transmission_curve[1] is the energetic transmission.         notes: string             Notes about the filter is any. Object giving access to the module database.      This object can be used in a context manager. Create a connection manager to the module database          writable : boolean             If true, the users will have write access to the database             provided they can write the sqlite file. By default, it's             false. Upgrade the table schemas in the database. Close the connection to the database. Retrieves HELP fields information.      This function retrieves information about HELP fields in the database. The     return depends on the arguments.      - If there is only one argument, the function returns the field       corresponding to the name given in argument. If there is no field with       that name, None is returned.     - If there are several arguments, the function return the list of fields       corresponding to the given names. If none of the given names correspond       to actual fields, an empty list is returned.     - If no argument is given, the function returns the list of all the HELP       fields.      Each field is returned as a Field object with these attributes:      - name: the full name of the field;     - short_id: its three letters identifier;     - footprint: its footprint as a pymoc.MOC object.      Parameters     ----------     *args : str         Name or names (several arguments, not a list of names) of the fields.      Returns     -------     Field or list of fields         If exactly one argument is given returns a Field (or None) else returns         a list of fields. Retrieves HELP photometric filters information.      This function retrieves information about the photometric filters used in     HELP.  The return depends on the arguments.      - If there is only one argument, the function returns the filter       corresponding to the filter ID given in argument. If there is no filter       with that ID, None is returned.     - If there are several arguments, the function return the list of filters       corresponding to the given IDs. If none of the given IDs correspond to       actual filters, an empty list is returned.     - If no argument is given, the function returns the list of all the filters       in the database.      Parameters     ----------     *args : str         ID or IDs (several arguments, not a list) of the filters.      Returns     -------     Filter or list of Filters         If exactly one argument is given returns a Filter (or None) else         returns a list of filters.