text: import os
  import shutil
  from argparse import Namespace
  from datetime import datetime
  from typing import Dict, List
  
  from fpakman.core import disk
  from fpakman.core.controller import ApplicationManager
  from fpakman.core.disk import DiskCacheLoader
  from fpakman.core.model import ApplicationData, Application, ApplicationUpdate
  from fpakman.core.snap import snap
  from fpakman.core.snap.model import SnapApplication
  from fpakman.core.snap.worker import SnapAsyncDataLoader
  from fpakman.core.system import FpakmanProcess
  from fpakman.util.cache import Cache
  
  
  class SnapManager(ApplicationManager):
  
      def __init__(self, app_args: Namespace,  api_cache: Cache, disk_cache: bool, http_session, locale_keys: dict):
          super(SnapManager, self).__init__(app_args=app_args, locale_keys=locale_keys)
          self.api_cache = api_cache
          self.http_session = http_session
          self.disk_cache = disk_cache
  
      def map_json(self, app_json: dict, installed: bool,  disk_loader: DiskCacheLoader) -> SnapApplication:
          app = SnapApplication(publisher=app_json.get('publisher'),
                                rev=app_json.get('rev'),
                                notes=app_json.get('notes'),
                                app_type=app_json.get('type'),
                                base_data=ApplicationData(id=app_json.get('name'),
                                                          name=app_json.get('name'),
                                                          version=app_json.get('version'),
                                                          latest_version=app_json.get('version'),
                                                          description=app_json.get('description')
                                                          ))
  
          if app.publisher:
              app.publisher = app.publisher.replace('*', '')
  
          app.installed = installed
  
          api_data = self.api_cache.get(app_json['name'])
          expired_data = api_data and api_data.get('expires_at') and api_data['expires_at'] <= datetime.utcnow()
  
          if (not api_data or expired_data) and not app.is_library():
              if disk_loader and app.installed:
                  disk_loader.add(app)
  
              SnapAsyncDataLoader(app=app, api_cache=self.api_cache, manager=self, http_session=self.http_session, download_icons=self.app_args.download_icons).start()
          else:
              app.fill_cached_data(api_data)
  
          return app
  
      def search(self, word: str, disk_loader: DiskCacheLoader) -> Dict[str, List[SnapApplication]]:
          installed = self.read_installed(disk_loader)
  
          res = {'installed': [], 'new': []}
  
          for app_json in snap.search(word):
  
              already_installed = None
  
              if installed:
                  already_installed = [i for i in installed if i.base_data.id == app_json.get('name')]
                  already_installed = already_installed[0] if already_installed else None
  
              if already_installed:
                  res['installed'].append(already_installed)
              else:
                  res['new'].append(self.map_json(app_json, installed=False, disk_loader=disk_loader))
  
          return res
  
      def read_installed(self, disk_loader: DiskCacheLoader) -> List[SnapApplication]:
          return [self.map_json(app_json, installed=True, disk_loader=disk_loader) for app_json in snap.read_installed()]
  
      def downgrade_app(self, app: Application, root_password: str) -> FpakmanProcess:
          return FpakmanProcess(subproc=snap.downgrade_and_stream(app.base_data.name, root_password), wrong_error_phrase=None)
  
      def clean_cache_for(self, app: SnapApplication):
          self.api_cache.delete(app.base_data.name)
  
          if app.supports_disk_cache() and os.path.exists(app.get_disk_cache_path()):
              shutil.rmtree(app.get_disk_cache_path())
  
      def can_downgrade(self):
          return True
  
      def update_and_stream(self, app: SnapApplication) -> FpakmanProcess:
          pass
  
      def uninstall_and_stream(self, app: SnapApplication, root_password: str) -> FpakmanProcess:
          return FpakmanProcess(subproc=snap.uninstall_and_stream(app.base_data.name, root_password))
  
      def get_app_type(self):
          return SnapApplication
  
      def get_info(self, app: SnapApplication) -> dict:
          info = snap.get_info(app.base_data.name, attrs=('license', 'contact', 'commands', 'snap-id', 'tracking', 'installed'))
          info['description'] = app.base_data.description
          info['publisher'] = app.publisher
          info['revision'] = app.rev
          info['name'] = app.base_data.name
  
          if info.get('commands'):
              info['commands'] = ' '.join(info['commands'])
  
          return info
  
      def get_history(self, app: Application) -> List[dict]:
          return []
  
      def install_and_stream(self, app: SnapApplication, root_password: str) -> FpakmanProcess:
          return FpakmanProcess(subproc=snap.install_and_stream(app.base_data.name, app.confinement, root_password))
  
      def is_enabled(self) -> bool:
          return snap.is_installed()
  
      def cache_to_disk(self, app: Application, icon_bytes: bytes, only_icon: bool):
          if self.disk_cache and app.supports_disk_cache():
              disk.save(app, icon_bytes, only_icon)
  
      def requires_root(self, action: str, app: SnapApplication):
          return action != 'search'
  
      def refresh(self, app: SnapApplication, root_password: str) -> FpakmanProcess:
          return FpakmanProcess(subproc=snap.refresh_and_stream(app.base_data.name, root_password))
  
      def prepare(self):
          pass
  
      def list_updates(self) -> List[ApplicationUpdate]:
          return []
  
      def list_warnings(self) -> List[str]:
          if snap.get_snapd_version() == 'unavailable':
              return [self.locale_keys['snap.notification.snapd_unavailable']]
  
      def list_suggestions(self, limit: int) -> List[SnapApplication]:
  
          suggestions = []
  
          if limit != 0:
              for name in ('whatsdesk', 'slack', 'yakyak', 'instagraph', 'pycharm-professional', 'eclipse', 'gimp', 'supertuxkart'):
                  res = snap.search(name, exact_name=True)
                  if res:
                      suggestions.append(self.map_json(res[0], installed=False, disk_loader=None))
  
                  if len(suggestions) == limit:
                      break
  
          return suggestions
  