"""
Internal shared-state variables such as config settings and host lists.
"""

import os
import sys
from optparse import make_option

from fabric.network import HostConnectionCache, ssh
from fabric.version import get_version
from fabric.utils import _AliasDict, _AttributeDict


#
# Win32 flag
#

# Impacts a handful of platform specific behaviors. Note that Cygwin's Python
# is actually close enough to "real" UNIXes that it doesn't need (or want!) to
# use PyWin32 -- so we only test for literal Win32 setups (vanilla Python,
# ActiveState etc) here.
win32 = (sys.platform == 'win32')


#
# Environment dictionary - support structures
#

# By default, if the user (including code using Fabric as a library) doesn't
# set the username, we obtain the currently running username and use that.
def _get_system_username():
    """
    Obtain name of current system user, which will be default connection user.
    """
    import getpass
    username = None
    try:
        username = getpass.getuser()
    # getpass.getuser supported on both Unix and Windows systems.
    # getpass.getuser may call pwd.getpwuid which in turns may raise KeyError
    # if it cannot find a username for the given UID, e.g. on ep.io
    # and similar "non VPS" style services. Rather than error out, just keep
    # the 'default' username to None. Can check for this value later if needed.
    except KeyError:
        pass
    except ImportError:
        if win32:
            import win32api
            import win32security
            import win32profile
            username = win32api.GetUserName()
    return username

def _rc_path():
    """
    Return platform-specific default file path for $HOME/.fabricrc.
    """
    rc_file = '.fabricrc'
    rc_path = '~/' + rc_file
    expanded_rc_path = os.path.expanduser(rc_path)
    if expanded_rc_path == rc_path and win32:
            from win32com.shell.shell import SHGetSpecialFolderPath
            from win32com.shell.shellcon import CSIDL_PROFILE
            expanded_rc_path = "%s/%s" % (
                SHGetSpecialFolderPath(0, CSIDL_PROFILE),
                rc_file
                )
    return expanded_rc_path

default_port = '22'  # hurr durr
default_ssh_config_path = '~/.ssh/config'

# Options/settings which exist both as environment keys and which can be set on
# the command line, are defined here. When used via `fab` they will be added to
# the optparse parser, and either way they are added to `env` below (i.e.  the
# 'dest' value becomes the environment key and the value, the env value).
#
# Keep in mind that optparse changes hyphens to underscores when automatically
# deriving the `dest` name, e.g. `--reject-unknown-hosts` becomes
# `reject_unknown_hosts`.
#
# Furthermore, *always* specify some sort of default to avoid ending up with
# optparse.NO_DEFAULT (currently a two-tuple)! In general, None is a better
# default than ''.
#
# User-facing documentation for these are kept in docs/env.rst.
env_options = [

    make_option('-a', '--no_agent',
        action='store_true',
        default=False,
        help="don't use the running SSH agent"
    ),

    make_option('-A', '--forward-agent',
        action='store_true',
        default=False,
        help="forward local agent to remote end"
    ),

    make_option('--abort-on-prompts',
        action='store_true',
        default=False,
        help="abort instead of prompting (for password, host, etc)"
    ),

    make_option('-c', '--config',
        dest='rcfile',
        default=_rc_path(),
        metavar='PATH',
        help="specify location of config file to use"
    ),

    make_option('--colorize-errors',
        action='store_true',
        default=False,
        help="Color error output",
    ),

    make_option('-D', '--disable-known-hosts',
        action='store_true',
        default=False,
        help="do not load user known_hosts file"
    ),

    make_option('-e', '--eagerly-disconnect',
        action='store_true',
        default=False,
        help="disconnect from hosts as soon as possible"
    ),

    make_option('-f', '--fabfile',
        default='fabfile',
        metavar='PATH',
        help="python module file to import, e.g. '../other.py'"
    ),

    make_option('-g', '--gateway',
        default=None,
        metavar='HOST',
        help="gateway host to connect through"
    ),

    make_option('--hide',
        metavar='LEVELS',
        help="comma-separated list of output levels to hide"
    ),

    make_option('-H', '--hosts',
        default=[],
        help="comma-separated list of hosts to operate on"
    ),

    make_option('-i',
        action='append',
        dest='key_filename',
        metavar='PATH',
        default=None,
        help="path to SSH private key file. May be repeated."
    ),

    make_option('-k', '--no-keys',
        action='store_true',
        default=False,
        help="don't load private key files from ~/.ssh/"
    ),

    make_option('--keepalive',
        dest='keepalive',
        type=int,
        default=0,
        metavar="N",
        help="enables a keepalive every N seconds"
    ),

    make_option('--linewise',
        action='store_true',
        default=False,
        help="print line-by-line instead of byte-by-byte"
    ),

    make_option('-n', '--connection-attempts',
        type='int',
        metavar='M',
        dest='connection_attempts',
        default=1,
        help="make M attempts to connect before giving up"
    ),

    make_option('--no-pty',
        dest='always_use_pty',
        action='store_false',
        default=True,
        help="do not use pseudo-terminal in run/sudo"
    ),

    make_option('-p', '--password',
        default=None,
        help="password for use with authentication and/or sudo"
    ),

    make_option('-P', '--parallel',
        dest='parallel',
        action='store_true',
        default=False,
        help="default to parallel execution method"
    ),

    make_option('--port',
        default=default_port,
        help="SSH connection port"
    ),

    make_option('-r', '--reject-unknown-hosts',
        action='store_true',
        default=False,
        help="reject unknown hosts"
    ),

    make_option('--system-known-hosts',
        default=None,
        help="load system known_hosts file before reading user known_hosts"
    ),

    make_option('-R', '--roles',
        default=[],
        help="comma-separated list of roles to operate on"
    ),

    make_option('-s', '--shell',
        default='/bin/bash -l -c',
        help="specify a new shell, defaults to '/bin/bash -l -c'"
    ),

    make_option('--show',
        metavar='LEVELS',
        help="comma-separated list of output levels to show"
    ),

    make_option('--skip-bad-hosts',
        action="store_true",
        default=False,