# Copyright (c) 2013-2020, SIB - Swiss Institute of Bioinformatics and
#                          Biozentrum - University of Basel
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#   http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


"""
Uncategorised functions which may come handy at several places.
"""

import os
import sys
import ost

def MsgErrorAndExit(msg, exit_status):
    '''
    Send a messages to the |ost_s| :ost_docs:`error log <base/logging/>` and
    exit the Python interpreter.

    :param msg: The message.
    :type msg: :class:`str`

    :param exit_status: Exit code, ends up in ``$?`` in the shell. ``0`` is
                      traditionally reserved to successful commands.
    :type exit_status: :class:`int`

    :returns: No return value, exits script with value ``exit_status``.
    '''
    ost.LogError(msg)
    sys.exit(exit_status)

def FileExists(prefix, exit_status, filename):
    '''
    Checks if a file exists, terminates if not. The error message displayed is
    fixed and only needs a *prefix* describing the specimen of file.

    :param prefix: String to put in front of the failure-message
                   "file does not exist: ``file``".
    :type prefix: :class:`str`

    :param exit_status: Exit code on missing file, ends up in ``$?`` in the
           shell. ``0`` is traditionally reserved to successful commands.
    :type exit_status: :class:`int`

    :param file: Path including file name to be checked.
    :type file: :class:`str`

    :returns: No return value, exits script with value ``exit_status`` if file
              is missing.
    '''
    if not os.path.exists(filename):
        MsgErrorAndExit('%s file does not exist: %s\n' % (prefix, filename),
                        exit_status)

def FileGzip(prefix, exit_status, filename, allowed=True):
    '''
    See if a file is gzipped or not. This is basically done by checking for a
    "gz" suffix. May also be used to verify that a file is not compressed where
    it does not apply. That is where *allowed* comes in. If "gz" is not allowed,
    terminates the script on gzip files.

    :param prefix: String to put in front of the failure-message where gzip
                   files are not allowed.
    :type prefix: :class:`str`

    :param exit_status: Exit code on gzip files to be avoided, ends up in
                        ``$?`` in the shell. ``0`` is traditionally reserved to
                        successful commands.
    :type exit_status: :class:`int`

    :param filename: Path including file name to be checked.
    :type filename: :class:`str`

    :param allowed: Set to ``False`` if gzipped files are not allowed. Then the
                    script will terminate if a gzip file is found.
    :type allowed: :class:`bool`

    :returns: Flag to indicate if file is gzipped (:class:`bool`).
    '''
    _, fileext = os.path.splitext(filename)
    is_gz = False
    if fileext.lower() == '.gz':
        is_gz = True
        if not allowed:
            MsgErrorAndExit('%s file in Gzip not supported: %s. ' % (prefix,
                                                                     filename),
                            exit_status)
    return is_gz

def FileExtension(prefix, exit_status, filename, extensions, gzip=False):
    '''
    Checks a file to carry a known extension given by a list of strings. Since
    files are very often compressed these days, an additional "gz" suffix can be
    tracked automatically by this function. Thus, the list of *extensions* only
    needs to contain what you are really looking for, e.g. ("pdb") instead of
    ("pdb", "pdb.gz"). The *gzip* flag also determines the output of this
    function. If enabled, a triple is returned: name of the file without
    extension, its extension and a Boolean to tell whether the file carries the
    gzip extension or not. If *gzip* detection is turned of, only a tuple is
    returned: file name  and extension. If the tested file name has an
    unrecognised extension, this function terminates the script.

    :param prefix: String to put in front of the failure-message
                   "file extension not supported: ``filename``".
    :type prefix: :class:`str`

    :param exit_status: Exit code on missing file, ends up in ``$?`` in the
           shell. ``0`` is traditionally reserved to successful commands.
    :type exit_status: :class:`int`

    :param filename: Path including file name to be checked.
    :type filename: :class:`str`

    :param extensions: List of strings without a leading ".".
    :type extensions: :class:`list`

    :param gzip: Indicates whether to check for an additional "gz" extension.
    :type gzip: :class:`bool`

    :returns: (base name of ``filename`` (:class:`str`), extension of file
              without a ".gz" (:class:`str`), flag to indicate an additional
              ".gz" (:class:`bool`)) **if** ``gzip`` is set, (base name of
              ``filename`` (:class:`str`), extension of file) **if not**.
    '''
    pfilename, fileext = os.path.splitext(filename)
    is_gz = False
    if fileext.lower() == '.gz':
        is_gz = True
        pfilename, fileext = os.path.splitext(pfilename)
        if not gzip:
            extension_string = ', '.join(extensions)
            MsgErrorAndExit('%s file extension not supported: %s. ' %(prefix,
                                                                      filename)+
                            'Allowed extensions are: %s\n' % extension_string,
                            exit_status)
    if fileext == '':
        extension_string = ', '.join(extensions)
        if gzip:
            extension_string += ', ' + '.gz, '.join(extensions) + '.gz'
            MsgErrorAndExit('%s file extension not supported: %s. ' %(prefix,
                                                                      filename)+
                            'Allowed extensions are: %s\n' % extension_string,
                            exit_status)
    fileext = fileext[1:].lower()
    for ext in extensions:
        if fileext == ext.lower():
            if gzip:
                return os.path.basename(pfilename), fileext, is_gz
            else:
                return os.path.basename(pfilename), fileext
    extension_string = ', '.join(extensions)
    if gzip:
        extension_string += ', ' + '.gz, '.join(extensions) + '.gz'
    MsgErrorAndExit('%s file extension not supported: %s. ' % (prefix,
                                                               filename)+
                    'Allowed extensions are: %s\n' % extension_string,
                    exit_status)

__all__ = (
    'MsgErrorAndExit',
    'FileExists',
    'FileExtension',
)

#  LocalWords:  gzipped gz param str gzip bool
