__all__ = [
    'XarBundleDir',
    'make_xar_ops_dirs',
]

import logging
from pathlib import Path

import g1.files
from g1.bases.assertions import ASSERT
from g1.containers import scripts as ctr_scripts
from g1.texts import jsons

from . import bases
from . import models
from . import repos

LOG = logging.getLogger(__name__)


class XarBundleDir(repos.BundleDirInterface):

    deploy_instruction_type = models.XarDeployInstruction

    def __init__(self, path):
        self.path_unchecked = path

    def check(self):
        ASSERT.predicate(self.path_unchecked, Path.is_dir)
        if self.load_deploy_instruction().is_zipapp():
            ASSERT.predicate(
                self.path_unchecked / models.XAR_BUNDLE_ZIPAPP_FILENAME,
                Path.is_file,
            )
        else:
            ASSERT.predicate(
                self.path_unchecked / models.XAR_BUNDLE_IMAGE_FILENAME,
                Path.is_file,
            )

    @property
    def zipapp_path(self):
        ASSERT.true(self.deploy_instruction.is_zipapp())
        return self.path / models.XAR_BUNDLE_ZIPAPP_FILENAME

    @property
    def image_path(self):
        ASSERT.false(self.deploy_instruction.is_zipapp())
        return self.path / models.XAR_BUNDLE_IMAGE_FILENAME

    def install(self):
        if self.deploy_instruction.is_zipapp():
            LOG.info('xars install zipapp: %s %s', self.label, self.version)
            bases.copy_exec(
                self.zipapp_path,
                bases.get_zipapp_target_path(self.deploy_instruction.name),
            )
        else:
            LOG.info('xars install xar: %s %s', self.label, self.version)
            ctr_scripts.ctr_import_image(self.image_path)
            ctr_scripts.ctr_install_xar(
                self.deploy_instruction.name,
                self.deploy_instruction.exec_relpath,
                self.deploy_instruction.image,
            )
        return True

    def uninstall(self):
        if self.deploy_instruction.is_zipapp():
            LOG.info('xars uninstall zipapp: %s %s', self.label, self.version)
            path = bases.get_zipapp_target_path(self.deploy_instruction.name)
            if path.exists():
                path.unlink()
        else:
            LOG.info('xars uninstall xar: %s %s', self.label, self.version)
            ctr_scripts.ctr_uninstall_xar(self.deploy_instruction.name)
            ctr_scripts.ctr_remove_image(self.deploy_instruction.image)
        return True


class XarOpsDir(repos.OpsDirInterface):

    metadata_type = models.XarMetadata

    def __init__(self, path):
        self.path_unchecked = path

    def init(self):
        bases.make_dir(self.path_unchecked)

    def check(self):
        ASSERT.predicate(self.path_unchecked, Path.is_dir)

    @property
    def zipapp_target_path(self):
        ASSERT.true(self.metadata.is_zipapp())
        return bases.get_zipapp_target_path(self.metadata.name)

    def cleanup(self):
        if self._metadata_path.exists():
            self._metadata_path.unlink()
        ASSERT.predicate(self.path, g1.files.is_empty_dir)

    def check_invariants(self, active_ops_dirs):
        self.check()
        ASSERT.predicate(self.metadata_path, Path.is_file)
        for ops_dir in active_ops_dirs:
            ASSERT(
                ops_dir.metadata.name != self.metadata.name,
                'expect unique xar label name: {}, {}',
                ops_dir.label,
                self.label,
            )

    def init_from_bundle_dir(self, bundle_dir, target_ops_dir_path):
        del target_ops_dir_path  # Unused.
        jsons.dump_dataobject(
            models.XarMetadata(
                label=bundle_dir.label,
                version=bundle_dir.version,
                image=bundle_dir.deploy_instruction.image,
            ),
            self.metadata_path,
        )
        bases.set_file_attrs(self.metadata_path)

    def activate(self):
        pass  # Nothing here.

    def deactivate(self):
        pass  # Nothing here.

    def uninstall(self):
        log_args = (self.metadata.label, self.metadata.version)
        if self.metadata.is_zipapp():
            LOG.info('xars uninstall zipapp: %s %s', *log_args)
            path = bases.get_zipapp_target_path(self.metadata.name)
            if path.exists():
                path.unlink()
        else:
            LOG.info('xars uninstall xar: %s %s', *log_args)
            ctr_scripts.ctr_uninstall_xar(self.metadata.name)
            ctr_scripts.ctr_remove_image(self.metadata.image)
        return True


def make_xar_ops_dirs():
    return repos.OpsDirs(
        models.REPO_XARS_DIR_NAME,
        bases.get_repo_path() / models.REPO_XARS_DIR_NAME,
        bundle_dir_type=XarBundleDir,
        ops_dir_type=XarOpsDir,
    )

@@ -1953,34 +1953,55 @@
 (self):%0A        
-if
+return _uninstall(self,
  self.deploy_ins
@@ -2000,32 +2000,144 @@
 ploy_instruction
+)%0A%0A%0Adef _uninstall(dir_obj, inst_like_obj):%0A    log_args = (dir_obj.label, dir_obj.version)%0A    if inst_like_obj
 .is_zipapp():%0A  
@@ -2126,36 +2126,32 @@
 bj.is_zipapp():%0A
-    
         LOG.info
@@ -2187,190 +2187,103 @@
 s', 
-self.label, self.version)%0A            path = bases.get_zipapp_target_path(self.deploy_instruction.name)%0A            if path.exists():%0A                path.unlink()%0A  
+*log_args)%0A        g1.files.remove(bases.get_zipapp_target_path(inst_like_obj.name))%0A
     
-  
 else:%0A
-    
     
@@ -2328,38 +2328,19 @@
 s', 
-self.label, self.version)%0A    
+*log_args)%0A
     
@@ -2377,42 +2377,28 @@
 xar(
-self.deploy_instruction
+inst_like_obj
 .name)%0A
-    
     
@@ -2434,39 +2434,29 @@
 age(
-self.deploy_instruction
+inst_like_obj
 .image)%0A
     
@@ -2443,36 +2443,32 @@
 like_obj.image)%0A
-    
     return True%0A
@@ -2957,59 +2957,29 @@
     
-if self._metadata_path.exists():%0A            
+g1.files.remove(
 self.
-_
 meta
@@ -2983,32 +2983,24 @@
 etadata_path
-.unlink(
 )%0A        AS
@@ -4003,396 +4003,15 @@
     
-log_args = (self.metadata.label, self.metadata.version)%0A        if self.metadata.is_zipapp():%0A            LOG.info('xars uninstall zipapp: %25s %25s', *log_args)%0A            path = bases.get_zipapp_target_path(self.metadata.name)%0A            if path.exists():%0A                path.unlink()%0A        else:%0A            LOG.info('xars uninstall xar: %25s %25s', *log_args)%0A            ctr_scripts.ctr
+return 
 _uni
@@ -4020,114 +4020,29 @@
 tall
-_xar
 (self
-.metadata.name)%0A            ctr_scripts.ctr_remove_image(self.metadata.image)%0A        return True
+, self.metadata)
 %0A%0A%0Ad

Refactor xar ops dir uninstall