#
#  Licensed to the Apache Software Foundation (ASF) under one or more
#  contributor license agreements.  See the NOTICE file distributed with
#  this work for additional information regarding copyright ownership.
#  The ASF licenses this file to You 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.
#

''' Endpoints for retrieving directory information from the server. '''

from bottle import Bottle, request, response
import os
import re

from config import WORK_DIR, PATH_LEADER

dir_app = Bottle()

@dir_app.route('/list/')
@dir_app.route('/list/<dir_path:path>')
def get_directory_info(dir_path='/'):
    ''' Return the listing of a supplied path.

    :param dir_path: The directory path to list.
    :type dir_path: String

    :returns: Dictionary containing the directory listing if possible.

    **Example successful JSON return**

    .. sourcecode:: javascript

        {
            'listing': [
                '/bar/',
                '/baz.txt',
                '/test.txt'
            ]
        }

    **Example failure JSON return**

    .. sourcecode:: javascript

        {'listing': []}
    '''
    dir_info = []

    try:
        clean_path = _get_clean_directory_path(PATH_LEADER, dir_path)
        dir_listing = os.listdir(clean_path)
    except:
        # ValueError - dir_path couldn't be 'cleaned'
        # OSError - clean_path is not a directory
        # Either way, we don't have anything to list for the directory!
        pass
    else:
        for obj in dir_listing:
            # Ignore hidden files
            if obj[0] == '.': continue

            # Create a path to the listed object. If it's a directory add a
            # trailing slash as a visual clue. Then strip out the path leader.
            obj = os.path.join(clean_path, obj)
            if os.path.isdir(obj): obj = obj + '/'
            dir_info.append(obj.replace(PATH_LEADER, ''))

        sorted(dir_info, key=lambda s: s.lower())

    if request.query.callback:
        return "%s(%s)" % (request.query.callback, {'listing': dir_info})
    return {'listing': dir_info}

@dir_app.route('/results/')
def get_result_dir_info():
    ''' Retrieve results directory information.

    The backend's results directory is determined by WORK_DIR. All the 
    directories there are formatted and returned as results. If WORK_DIR does
    not exist, an empty listing will be returned (shown as a 'failure below').

    **Successful JSON Response**

    .. sourcecode:: javascript

        {
            'listing': [
                '/bar',
                '/foo'
            ]
        }

    **Failure JSON Response**

    .. sourcecode:: javascript

        {
            'listing': []
        }
    '''
    dir_info = []

    try:
        dir_listing = os.listdir(WORK_DIR)
    except OSError:
        # The WORK_DIR hasn't been created, so we don't have any results!
        pass
    else:
        for obj in dir_listing:
            # Ignore hidden files
            if obj[0] == '.': continue

            # Create a path to the listed object and strip the work dir leader.
            # If the result isn't a directory, ignore it.
            obj = os.path.join(WORK_DIR, obj)
            if not os.path.isdir(obj): continue
            dir_info.append(obj.replace(WORK_DIR, ''))

        sorted(dir_info, key=lambda s: s.lower())

    if request.query.callback:
        return "%s(%s)" % (request.query.callback, {'listing': dir_info})
    return {'listing': dir_info}

@dir_app.route('/results/<dir_path:path>')
def get_results(dir_path):
    ''' Retrieve specific result files.

    :param dir_path: The relative results path to list.
    :type dir_path: String

    :returns: Dictionary of the requested result's directory listing.

    **Successful JSON Response**

    .. sourcecode:: javascript

        {
            'listing': [
                'file1',
                'file2'
            ]
        }

    **Failure JSON Response**

    .. sourcecode:: javascript

        {
            'listing': []
        }
    '''
    dir_info = []

    try:
        clean_path = _get_clean_directory_path(WORK_DIR, dir_path)
        dir_listing = os.listdir(clean_path)
    except:
        # ValueError - dir_path couldn't be 'cleaned'
        # OSError - clean_path is not a directory
        # Either way, we don't have any results to return!
        pass
    else:
        for obj in dir_listing:
            # Ignore hidden files
            if obj[0] == '.': continue

            # Create a path to the listed object and strip out the path leader.
            obj = os.path.join(clean_path, obj)
            dir_info.append(obj.replace(WORK_DIR, ''))

        sorted(dir_info, key=lambda s: s.lower())

    if request.query.callback:
        return "%s(%s)" % (request.query.callback, {'listing': dir_info})
    return {'listing': dir_info}

@dir_app.route('/path_leader/')
def get_path_leader():
    ''' Return the path leader used for clean path creation.

    **Example JSON Response**

    .. sourcecode:: javascript

        {'leader': '/usr/local/ocw'}
    '''
    return_json = {'leader': PATH_LEADER}

    if request.query.callback:
        return "%s(%s)" % (request.query.callback, return_json)
    return return_json

@dir_app.hook('after_request')
def enable_cors():
    ''' Allow Cross-Origin Resource Sharing for all URLs. '''
    response.headers['Access-Control-Allow-Origin'] = '*'

def _get_clean_directory_path(path_leader, dir_path):
    ''' Return a cleaned directory path with a defined path prefix.

    'Clean' dir_path to remove any relative path components or duplicate 
    slashes that could cause problems. The final clean path is then the
    path_leader + dir_path.

    :param path_leader: The path prefix that will be prepended to the cleaned
        dir_path.
    :type path_leader: String
    :param dir_path: The path to clean.
    :type path_leader: String
    
    :returns: The cleaned directory path with path_leader prepended.
    '''
    # Strip out any .. or . relative directories and remove duplicate slashes
    dir_path = re.sub('/[\./]*/?', '/', dir_path)
    dir_path = re.sub('//+', '/', dir_path)

    # Prevents the directory path from being a substring of the path leader.
    # os.path.join('/usr/local/ocw', '/usr/local') gives '/usr/local'
    # which could allow access to unacceptable paths. This also means that
    if dir_path[0] == '/': dir_path = dir_path[1:]

    return os.path.join(path_leader, dir_path)
