# Copyright 2013 VMware, Inc.  All rights reserved. -- VMware Confidential
#
'''
This module provides the local transport functionality needed to perform the base
operations on target machine.
'''
import logging
import os

from transport import FileException

logger = logging.getLogger(__name__)

def _createDirectory(path):
    '''Create the directory, recursively, with given path.

    @param path: Directory path
    '''
    os.makedirs(path)

def fileExists(path):
    '''Tests if the file exists.

    @param path: File or Directory path
    @type path: str

    @returns: True if file exists, otherwise False.
    @rtype : boolean
    '''
    return os.path.exists(path)

def isFile(path):
    '''Tests if the target path exists and is a regular file.

    @param path: File path
    @type targetPath: str

    @return: True if path exists and is regular file, otherwise False
    @rtype: boolean
    '''
    return os.path.isfile(path)

def isDirectory(path):
    '''Tests if the path exists and is a valid directory.

    @param path: Directory path
    @type path: str

    @return: True if path exists and is regular directory, otherwise False
    @rtype: boolean
    '''
    return os.path.isdir(path)

def ensureFileExists(filePath, isFileExpected, isLocal=True):
    '''Ensure file path exists and it is the expected type.

    @param filePath: File path
    @type filePath: str

    @param isFileExpected: Specifies if given file path is a file or
      a directory path. True if expect file and false if expect directory.
    @type isFileExpected: boolean

    @param isLocal: Specifies if the file path is local or target file
      path. The param will be used to set the proper exception message
    @type isLocal: boolean

    @raise FileException: If
      * filePath does not exist
      * filePath exists but it is not expected file or dir.
    '''
    error = None
    if fileExists(filePath):
        if isFileExpected and not isFile(filePath):
            if isLocal:
                error = 'Local file %s is not a regular file' % filePath
            else:
                error = 'Target file %s is not a regular file' % filePath
        if not isFileExpected and not isDirectory(filePath):
            if isLocal:
                error = 'Local dir %s is not a valid directory' % filePath
            else:
                error = 'Target dir %s is not a valid directory' % filePath
    else:
        if isFileExpected and isLocal:
            error = 'Local file %s does not exist' % filePath
        elif isFileExpected and not isLocal:
            error = 'Target file %s does not exist' % filePath
        elif not isFileExpected and isLocal:
            error = 'Local directory %s does not exist' % filePath
        else:
            error = 'Target directory %s does not exist' % filePath

    if error:
        logger.warning(error)
        raise FileException(error)

def ensureFileCanBeCreated(filePath, createPath, isFileExpected, isLocal=True):
    '''Ensure that file path exits or could be created.

    @param filePath: File path
    @type filePath: str

    @param createPath: Whether to create the path to given file in case
      it does not exist.
    @type createPath: boolean

    @param isFileExpected: Specifies if given file path is a file or
      a directory path. True if expect file and false if expect directory.
    @type isFileExpected: boolean

    @param isLocal: Specifies if the file path is local or target file
      path. The param will be used to set the proper exception message
    @type isLocal: boolean

    @raise FileException: If
      * filePath exists but it is not expected file or dir.
      * parent dir does not exist and createPath is set to False
      * parent dir exists but is not a valid directory.
    '''
    error = None
    if fileExists(filePath):
        ensureFileExists(filePath, isFileExpected, isLocal)
    else:
        # Check if parent dir exists or can be created
        parentDir = os.path.dirname(os.path.abspath(filePath))
        if not fileExists(parentDir) and not createPath:
            if isLocal:
                error = "Local parent directory %s does not exist." % parentDir
            else:
                error = "Target parent directory %s does not exist." % parentDir
        elif not fileExists(parentDir) and createPath:
            _createDirectory(parentDir)
        elif fileExists(parentDir) and not isDirectory(parentDir):
            if isLocal:
                error = 'Local parent directory %s is not a valid directory'\
                        % parentDir
            else:
                error = 'Target parent directory %s is not a valid directory'\
                        % parentDir

    if error:
        logger.warning(error)
        raise FileException(error)