# Copyright (c) 2010 Google Inc. All rights reserved.
# Copyright (c) 2009 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import logging
import os
import sys

from webkitpy.common.checkout import Checkout
from webkitpy.common.checkout.scm.detection import SCMDetector
from webkitpy.common.memoized import memoized
from webkitpy.common.system.systemhost import SystemHost
from webkitpy.common.watchlist.watchlistparser import WatchListParser
from webkitpy.port.factory import PortFactory


_log = logging.getLogger(__name__)


class Host(SystemHost):
    def __init__(self):
        SystemHost.__init__(self)
        self._checkout = None

        # FIXME: Unfortunately Port objects are currently the central-dispatch objects of the NRWT world.
        # In order to instantiate a port correctly, we have to pass it at least an executive, user, scm, and filesystem
        # so for now we just pass along the whole Host object.
        # FIXME: PortFactory doesn't belong on this Host object if Port is going to have a Host (circular dependency).
        self.port_factory = PortFactory(self)

        self._engage_awesome_locale_hacks()

    @property
    @memoized
    def bugs(self):
        from webkitpy.common.net import bugzilla
        return bugzilla.Bugzilla()

    @property
    @memoized
    def buildbot(self):
        from webkitpy.common.net import buildbot
        return buildbot.BuildBot()

    @property
    @memoized
    def web(self):
        from webkitpy.common.net import web
        return web.Web()

    # We call this from the Host constructor, as it's one of the
    # earliest calls made for all webkitpy-based programs.
    def _engage_awesome_locale_hacks(self):
        # To make life easier on our non-english users, we override
        # the locale environment variables inside webkitpy.
        # If we don't do this, programs like SVN will output localized
        # messages and svn.py will fail to parse them.
        # FIXME: We should do these overrides *only* for the subprocesses we know need them!
        # This hack only works in unix environments.
        os.environ['LANGUAGE'] = 'en'
        os.environ['LANG'] = 'en_US.UTF-8'
        os.environ['LC_MESSAGES'] = 'en_US.UTF-8'
        os.environ['LC_ALL'] = 'en_US.UTF-8'

    def initialize_scm(self, patch_directories=None):
        detector = SCMDetector(self.filesystem, self.executive)
        self._checkout = Checkout(detector.default_scm(patch_directories))

    def scm(self):
        return self._checkout._scm

    def checkout(self):
        return self._checkout

    @memoized
    def watch_list(self):
        config_path = self.filesystem.dirname(self.filesystem.path_to_module('webkitpy.common.config'))
        watch_list_full_path = self.filesystem.join(config_path, 'watchlist')
        if not self.filesystem.exists(watch_list_full_path):
            raise Exception('Watch list file (%s) not found.' % watch_list_full_path)

        watch_list_contents = self.filesystem.read_text_file(watch_list_full_path)
        return WatchListParser().parse(watch_list_contents)
