# coding=utf-8
# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).

from __future__ import (absolute_import, division, generators, nested_scopes, print_function,
                        unicode_literals, with_statement)

import os
from hashlib import sha1

from pants.backend.android.targets.android_library import AndroidLibrary
from pants.backend.android.targets.android_resources import AndroidResources
from pants.backend.core.tasks.task import Task
from pants.backend.jvm.targets.jar_dependency import JarDependency
from pants.backend.jvm.targets.jar_library import JarLibrary
from pants.base.address import Address
from pants.base.build_environment import get_buildroot
from pants.base.fingerprint_strategy import DefaultFingerprintStrategy
from pants.fs.archive import ZIP


class AndroidLibraryFingerprintStrategy(DefaultFingerprintStrategy):

  def compute_fingerprint(self, target):
    """AndroidLibrary targets need to be re-unpacked if any of the imported jars have changed."""
    # TODO(mateor) Create a utility function to add a block of fingerprints to a hasher with caller
    # handing in list of items of the same type and a function to extract a fingerprint from each.
    if isinstance(target, AndroidLibrary):
      hasher = sha1()
      for jar_import in sorted(target.imported_jars, key=lambda t: t.id):
        hasher.update(jar_import.cache_key())
      hasher.update(target.payload.fingerprint())
      return hasher.hexdigest()
    return None


class UnpackLibraries(Task):
  """Unpack AndroidDependency artifacts, including .jar and .aar libraries.

  The UnpackLibraries task unpacks artifacts imported by AndroidLibraries, as .aar or .jar files,
  through a 'libraries' attribute. The .aar files may contain components which require creation
  of some synthetic targets, as well as a classes.jar. The classes.jar is packaged into a
  JarDependency target and sent to javac compilation. All jar files are then unpacked-
  android_binaries repack the class files of all the android_libraries in their transitive
  dependencies into a dex file.

  All archives are unpacked only once, regardless of differing include/exclude patterns or how many
  targets depend upon it. All targets that depend on a particular artifact will be passed the
  unpack_libraries product, which is a directory containing the entire source of the unpacked jars.
  These sources are filtered against the AndroidLibrary's include/exclude patterns during the
  creation of the dex file.
  """

  class MissingElementException(Exception):
    """Raised if an unpacked file or directory unexpectedly does not exist."""

  class UnexpectedArchiveType(Exception):
    """Raised if an archive has an extension that is not explicitly handled by this class."""