# Copyright 2013 Daniel Narvaez
#
# 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.

import os
import subprocess
import urlparse

from osbuild import command
from osbuild import config
from osbuild import utils


def _chdir(func):
    def wrapped(*args, **kwargs):
        orig_cwd = os.getcwd()

        os.chdir(args[0].local)
        result = func(*args, **kwargs)
        os.chdir(orig_cwd)

        return result

    return wrapped


class Module:
    def __init__(self, path=None, name=None, remote=None,
                 branch="master", tag=None, retry=10):
        if path is None or name is None or remote is None:
            raise RuntimeError("path, name and remote are required")

        self._compute_remotes(remote)

        self.local = os.path.join(path, name)
        self.tag = tag

        self._path = path
        self._name = name
        self._branch = branch
        self._retry = 10

    def _compute_remotes(self, remote):
        parsed_url = urlparse.urlparse(remote)

        self._remotes = {"origin": remote}

        if parsed_url.netloc != "github.com":
            return

        prefs = config.get_prefs().get("github", {})

        name = os.path.basename(parsed_url.path)

        if parsed_url.path[1:] in prefs.get("ssh", []):
            self._remotes["origin"] = "git@github.com:%s" % parsed_url.path

        for fork in prefs.get("forks", []):
            if name == os.path.basename(fork):
                self._remotes["upstream"] = self._remotes["origin"]
                self._remotes["origin"] = "git@github.com:/%s" % fork

    def _clone(self):
        os.chdir(self._path)

        command.run(["git", "clone", "--progress", self._remotes["origin"],
                     self._name], retry=self._retry)

        os.chdir(self.local)

        for name, remote in self._remotes.items():
            if name != "origin":
                command.run(["git", "remote", "add", name, remote])

        if config.git_user_name:
            command.run(["git", "config", "user.name", config.git_user_name])

        if config.git_email:
            command.run(["git", "config", "user.email", config.git_email])

        if self.tag:
            command.run(["git", "checkout", self.tag])
        else:
            command.run(["git", "checkout", self._branch])

    def exists(self):
        return os.path.exists(os.path.join(self.local, ".git"))

    def update(self, revision=None):
        if not self.exists():
            self._clone()
            return

        os.chdir(self.local)

        if revision is None:
            revision = self.tag

        command.run(["git", "remote", "set-url", "origin",
                     self._remotes["origin"]])
        command.run(["git", "fetch"], retry=self._retry)

        if revision:
            command.run(["git", "checkout", revision])
        else:
            command.run(["git", "checkout", self._branch])
            command.run(["git", "merge", "--ff-only",
                         "origin/%s" % self._branch])

    @_chdir
    def checkout(self, revision=None):
        if revision is None:
            revision = self.tag
            if revision is None:
                revision = self._branch

        command.run(["git", "checkout", revision])

    @_chdir
    def describe(self):
        return subprocess.check_output(["git", "describe"]).strip()

    @_chdir
    def get_annotation(self, tag):
        # FIXME this is fragile, there must be a better way

        show = subprocess.check_output(["git", "show", tag])

        annotation = []
        for line in show.split("\n"):
            ignore = False
            for start in ["tag ", "Tagger: ", "Date: "]:
                if line.startswith(start):
                    ignore = True

            if line.startswith("commit "):
                break

            if not ignore:
                annotation.append(line)

        return "\n".join(annotation)

    @_chdir
    def clean(self):
        result = True

        if not config.interactive:
            command.run(["git", "clean", "-fdx"])
            command.run(["git", "reset", "--hard"])
            return result

        command.run(["git", "clean", "-fdX"])

        files = subprocess.check_output(["git", "ls-files",
                                         "--others"]).strip()
        if files:
            print("\n# The repository contains files which have not been "
                  "added to the index:\n")
            print(files)
            print("\nPress d to delete them, k to keep them.\n")

            while True:
                key = utils.getch()
                if key == "d":
                    command.run(["git", "clean", "-fdx"])
                    break
                elif key == "k":
                    result = False
                    break

        added = subprocess.check_output(["git", "diff", "--cached",
                                         "--name-only"]).strip()
        modified = subprocess.check_output(["git", "ls-files",
                                            "--modified"]).strip()
        deleted = subprocess.check_output(["git", "ls-files",
                                           "--deleted"]).strip()

        if added or modified or deleted:
            print("\n# The repository content has been modified.")

            if added:
                print("\nAdded files:")
                print(added)

            if modified:
                print("\nModified files:")
                print(modified)

            if deleted:
                print("\nDeleted files")
                print(deleted)

            print("\nPress r to reset the changes, k to keep them.\n")

            while True:
                key = utils.getch()
                if key == "r":
                    command.run(["git", "reset", "--hard"])
                    break
                elif key == "k":
                    result = False
                    break

        return result


def get_module(module):
    return Module(path=config.get_source_dir(),
                  name=module.name,
                  remote=module.repo,
                  branch=module.branch,
                  tag=module.tag,
                  retry=10)

@@ -3754,679 +3754,8 @@
 %5D)%0A%0A
-    @_chdir%0A    def describe(self):%0A        return subprocess.check_output(%5B%22git%22, %22describe%22%5D).strip()%0A%0A    @_chdir%0A    def get_annotation(self, tag):%0A        # FIXME this is fragile, there must be a better way%0A%0A        show = subprocess.check_output(%5B%22git%22, %22show%22, tag%5D)%0A%0A        annotation = %5B%5D%0A        for line in show.split(%22%5Cn%22):%0A            ignore = False%0A            for start in %5B%22tag %22, %22Tagger: %22, %22Date: %22%5D:%0A                if line.startswith(start):%0A                    ignore = True%0A%0A            if line.startswith(%22commit %22):%0A                break%0A%0A            if not ignore:%0A                annotation.append(line)%0A%0A        return %22%5Cn%22.join(annotation)%0A%0A
     

Drop unused code