class ComponentDevDir(object):
    '''Represents a component in the development directory'''

    def __init__(self, dir_path):
        self.path = dir_path
        print "Config Path", self.config_path
        self.config = ComponentConfig(self.config_path)

    @property
    def config_path(self):
        return os.path.join(self.path, 'component.ini')
    
    @property
    def is_valid(self):
        if not os.path.exists(self.path):
            return False
        if not os.path.exists(self.config_path):
            return False
        return True


    # -- Temporary Folder: A temporary working location -----------------------

    @property
    def _temp_path(self):
        return os.path.join(self.path, 'tmp')
    

    def clean_tmp(self):
        if os.path.exists(self._temp_path):
            shutil.rmtree(self._temp_path)


    def make_tmp(self):
        '''Create temporary directory to work in'''
        self.clean_tmp()
        os.mkdir(self._temp_path)
        return self._temp_path


    # -- Source Folder: Holds origional component files -----------------------

    @property
    def source_path(self):
        return os.path.join(self.path, 'source')
    

    def clean_source(self):
        if os.path.exists(self.source_path):
            shutil.rmtree(self.source_path)
        os.mkdir(self.source_path)


    # -- Download file source -------------------------------------------------
    
    def retrieve_source(self):
        '''Utility to download/retrieve the source for a component'''
        if self.config.source_type == self.config.SOURCE_DL_AND_UNPACK:

            tmp = self.make_tmp()
            archive_filename = self.config.url.split('/')[-1]
            archive_path = os.path.join(tmp, archive_filename)

            # Download
            print "Downloading", self.config.url
            remotefile = urllib2.urlopen(self.config.url)
            with open(archive_path, 'wb') as fh:
                data = remotefile.read(4096)
                while data:
                    fh.write(data)
                    data = remotefile.read(4096)

            # Unpack tar.gz
            unpack_path = os.path.join(tmp, 'unpacked')
            os.mkdir(unpack_path)

            if archive_filename.lower().endswith('.tar.gz'):


                print "  Uncompressing", archive_filename
                tar = tarfile.open(archive_path)
                tar.extractall(unpack_path)
                tar.close()

            if archive_filename.lower().endswith('.zip'):
                raise NotImplementedError()

            # Move to source/
            print "  Removing", self.source_path
            self.clean_source()
            print "  Copying new source into", self.source_path
            for dirpath, dirnames, filenames in os.walk(unpack_path):

                # Make dir path relative
                if not dirpath.startswith(unpack_path):
                    raise Exception("%s didn't start with %s" % (
                        dirpath, unpack_path))
                rel_dir_path = dirpath[len(unpack_path):]
                while len(rel_dir_path) > 0 and rel_dir_path[0] == '/':
                    rel_dir_path = rel_dir_path[1:]

                # Map to expected source path
                source_rel_dirpath = self.config.translate_archive_path(
                    rel_dir_path)

                if source_rel_dirpath is None:
                    continue

                # Make directories
                for dirname in dirnames:
                    os.mkdir(os.path.join(self.source_path,
                        source_rel_dirpath, dirname))

                # Move files
                for filename in filenames:
                    path = os.path.join(unpack_path, rel_dir_path, filename)
                    new_path = os.path.join(self.source_path, source_rel_dirpath,
                        filename)
                    os.rename(path, new_path)

            self.clean_tmp()

        else:
            msg = 'Source type not implemented: ' + self.config.source_type
            raise NotImplementedError(msg)

#   http://ftp.drupal.org/files/projects/drupal-7.36.tar.gz
    def execute(self):
        flags = gflags.FLAGS

        tree = find_dev_repo_obj()

        # Make sure components directory exists
        components_path = os.path.join(tree.path, 'components')
        if not os.path.exists(components_path):
            self.inform_user_of_action("Creating " + components_path)
            os.mkdir(components_path)

        name = self.ask_simple('name',
            "Name for this component",
            default = flags.name)

        path = os.path.join(components_path, name)
        if os.path.exists(path):
            raise ActionAbort("%s already exists" % (path))

        # Component type
        stype = self.ask_select('type',
            "How is this compontent obtained",
            options=[
                ComponentConfig.SOURCE_DL_AND_UNPACK,
                "git_clone",
                "custom_integrated"
                ])

        url = None
        if stype == ComponentConfig.SOURCE_DL_AND_UNPACK:
            url = self.ask_simple("url",
                "Url to download")
        else:
            raise NotImplementedError()

        version = self.ask_simple('version',
            "Current version of the component")

        MAP_TPLS = {
            'module': [
                (name, 'sites/all/modules/%s' % (name)),
                ],
            'theme': [
                (name, 'sites/all/themes/%s' % (name)),
                ],
            'library': [
                (name, 'sites/all/libraries/%s' % (name)),
                ],
            'base': [
                ('*', 'www/{1}'),
                ],
            'other': [
                ],
            }

        map_type = self.ask_select('map_type',
            "What type of component is this",
            options=['module', 'theme', 'library', 'base', 'other'])

        # -- Write package attribtes -----------------------------------------

        self.inform_user_of_action("Creating " + path)
        os.mkdir(path)

        config_path = os.path.join(path, 'component.ini')
        config = ComponentConfig(config_path)

        # Version
        config.version = version

        # Source
        config.source_type = stype
        if stype == ComponentConfig.SOURCE_DL_AND_UNPACK:
            config.url = url
        else:
            raise NotImplementedError()

        # Archive root folder
        if map_type == 'base':
            config.archive_root = '{name}-{ver}'
        elif map_type in ['module', 'theme', 'library']:
            config.archive_root = '{name}'
        else:
            config.archive_root = '.'


        # Mappings
        for pattern in MAP_TPLS[map_type]:
            config.add_mapping(ComponentFileMap(pattern[0], pattern[1]))

        # self.inform_user_of_action("Writing " + config_path)
        config.save()

        sub_path = os.path.join(path, 'source')
        self.inform_user_of_action("Creating " + sub_path)
        os.mkdir(sub_path)

        # Download
        self.inform_user_of_action("Downloading component source")
        tree.get_component(name).retrieve_source()
 def __init__(self, dir_path):
     self.path = dir_path
     print "Config Path", self.config_path
     self.config = ComponentConfig(self.config_path)