import os
import tarfile

from parallels.core.utils.common import open_no_inherit
from parallels.core.utils.file_utils import read_file_contents
from plesk_migrator.compatibility.utils import stringio


def tar_add_file_content(tar, content, filename):
    tarinfo = tarfile.TarInfo(filename)
    source = stringio(content, is_unicode=False)
    tarinfo.size = len(source.getvalue())
    tar.addfile(tarinfo, source)


def tar_add_empty_file(tar, filename):
    tarinfo = tarfile.TarInfo(filename)
    tarinfo.size = 0
    tar.addfile(tarinfo)


def tar_add_dir(tar, dirname):
    tarinfo = tarfile.TarInfo(dirname)
    tarinfo.type = tarfile.DIRTYPE
    tar.addfile(tarinfo)


def tar_directory(directory, archive):
    """Pack directory contents to tar file

    For example if we have directory '/root/test' passed as the first argument, which contains files:
    /root/test/a.txt
    /root/test/b/c.txt

    Then we will get tar file with contents:
    a.txt
    b/c.txt

    :param str directory: name of a directory to pack contents of
    :param str archive: name of tar file to pack contents to
    :rtype: None
    """
    with open_no_inherit(archive, 'wb') as fileobj:
        with tarfile.open(fileobj=fileobj, mode='w') as f:
            for root, _, files in os.walk(directory):
                for filename in files:
                    file_contents = read_file_contents(os.path.join(root, filename))
                    relative_path = os.path.relpath(os.path.join(root, filename), directory)
                    tar_info = tarfile.TarInfo(relative_path)
                    tar_info.size = len(file_contents)
                    f.addfile(tar_info, stringio(file_contents, is_unicode=False))


def untar(filename, directory):
    """Unpack TAR file to a directory

    :type filename: str | unicode
    :type directory: str | unicode
    :rtype: None
    """
    with tarfile.TarFile(filename) as fp:
        fp.extractall(directory)
