# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright (c) 2016, Anaconda, Inc. All rights reserved.
#
# Licensed under the terms of the BSD 3-Clause License.
# The full license is in the file LICENSE.txt, distributed with this software.
# -----------------------------------------------------------------------------
from __future__ import absolute_import, print_function

import os
import shutil
import tempfile
import zipfile

from anaconda_project.internal import rename


# we overwrite as long as the zip contains a file and target_path
# is a file, or the zip is a dir and target_path is a dir, but if
# they don't match we don't overwrite. Hopefully this will catch
# most mistaken collisions.
def unpack_zip(zip_path, target_path, errors):
    try:
        with zipfile.ZipFile(zip_path, mode='r') as zf:
            target_dir, target_file = os.path.split(target_path)
            tmp_dir = tempfile.mkdtemp(prefix=(target_path + "_tmp"), dir=target_dir)
            try:
                zf.extractall(tmp_dir)
                extracted = os.listdir(tmp_dir)
                if len(extracted) == 0:
                    errors.append("Zip archive was empty.")
                    return False
                elif len(extracted) == 1 and extracted[0] == target_file:
                    # don't keep a pointless directory level, if
                    # the zip just contains a single directory or
                    # file with the same name as the target
                    src_path = os.path.join(tmp_dir, extracted[0])
                else:
                    src_path = tmp_dir
                src_is_dir = os.path.isdir(src_path)
                target_is_dir = os.path.isdir(target_path)
                if os.path.exists(target_path) and (src_is_dir != target_is_dir):
                    if src_is_dir:
                        errors.append(
                            "%s exists and isn't a directory, not unzipping a directory over it." % target_path)
                    else:
                        errors.append("%s exists and is a directory, not unzipping a plain file over it." % target_path)
                    return False
                else:
                    rename.rename_over_existing(src_path, target_path)
            finally:
                if os.path.isdir(tmp_dir):
                    shutil.rmtree(path=tmp_dir)
            return True
    except Exception as e:
        errors.append("Failed to unzip %s: %s" % (zip_path, str(e)))
        return False
