# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Mobius Forensic Toolkit
# Copyright (C) 2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019 Eduardo Aguiar
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
import pymobius
import pymobius.extension
import mobius
import glob
import os
import os.path

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief Resource list
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
class ResourceList (object):

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief initialize object
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def __init__ (self):
    self.__resource_ids = []
    self.__resources = {}

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief iterate through resources
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def __iter__ (self):
    for resource_id in self.__resource_ids:
      yield resource_id, self.__resources.get (resource_id)

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief add resource
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def add (self, resource_id, resource):
    self.__resource_ids.append (resource_id)
    self.__resources[resource_id] = resource

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief remove resource
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def remove (self, resource_id):
    try:
      self.__resource_ids.remove (resource_id)
    except ValueError:
      pass

    self.__resources.pop (resource_id, None)

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief get resource
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def get (self, resource_id):
    return self.__resources.get (resource_id)


# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief Application class
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
class Application (object):

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief initialize object
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def __init__ (self):
    self.__resources = {}

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Run application
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def run (self):

    # resource services
    pymobius.mediator.advertise ('app.add-resource', self.svc_add_resource)
    pymobius.mediator.advertise ('app.remove-resource', self.svc_remove_resource)
    pymobius.mediator.advertise ('app.get-resource', self.svc_get_resource)
    pymobius.mediator.advertise ('app.list-resources', self.svc_list_resources)

    # extension data services
    pymobius.mediator.advertise ('extension.get-metadata', pymobius.extension.svc_extension_get_metadata)
    pymobius.mediator.advertise ('extension.get-metadata-from-file', pymobius.extension.svc_extension_get_metadata_from_file)
    pymobius.mediator.advertise ('extension.get-icon-data-from-file', pymobius.extension.svc_extension_get_icon_data_from_file)
    pymobius.mediator.advertise ('extension.get-icon-path', pymobius.extension.svc_extension_get_icon_path)
    pymobius.mediator.advertise ('extension.get-resource-path', pymobius.extension.svc_extension_get_resource_path)

    # extension running services
    pymobius.mediator.advertise ('extension.is-running', pymobius.extension.svc_extension_is_running)
    pymobius.mediator.advertise ('extension.start-api', pymobius.extension.svc_extension_start_api)
    pymobius.mediator.advertise ('extension.stop-api', pymobius.extension.svc_extension_stop_api)
    pymobius.mediator.advertise ('extension.start', pymobius.extension.svc_extension_start)
    pymobius.mediator.advertise ('extension.stop', pymobius.extension.svc_extension_stop)
    pymobius.mediator.advertise ('extension.start-all', pymobius.extension.svc_extension_start_all)
    pymobius.mediator.advertise ('extension.stop-all', pymobius.extension.svc_extension_stop_all)
    pymobius.mediator.advertise ('extension.list', pymobius.extension.svc_extension_list)
    pymobius.mediator.advertise ('extension.install', pymobius.extension.svc_extension_install)
    pymobius.mediator.advertise ('extension.uninstall', pymobius.extension.svc_extension_uninstall)

    # configure user account
    self.__configure_user ()

    # start extensions API
    pymobius.mediator.call ('extension.start-all')

    # start application
    pymobius.mediator.emit ('app.starting')
    pymobius.mediator.call ('app.start')
    
    # stop extensions
    pymobius.mediator.emit ('app.stopping')
    pymobius.mediator.call ('extension.stop-all')

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Configure application for current user
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def __configure_user (self):
    app = mobius.core.application ()
    extensions_dir = app.get_config_path ('extensions')

    if not os.path.exists (extensions_dir):
      os.makedirs (extensions_dir)
      dist_dir = app.get_data_path ('extensions')

      for path in sorted (glob.glob ('%s/*.mobius' % dist_dir)):
        print 'Installing extension %s' % os.path.basename (path)
        pymobius.extension.install (path)

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief service: app.add-resource
  # @param resource_id: resource ID
  # @param resource: resource object
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def svc_add_resource (self, resource_id, resource):
    if '.' in resource_id:
      group_id, item_id = resource_id.rsplit ('.', 1)
      resource_list = self.__resources.setdefault (group_id, ResourceList ())
      resource_list.add (item_id, resource)

      pymobius.mediator.emit ('app.resource-added', group_id, item_id, resource)

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief service: app.remove-resource
  # @param resource_id: resource ID
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def svc_remove_resource (self, resource_id):
    if '.' in resource_id:
      group_id, item_id = resource_id.rsplit ('.', 1)
      resource_list = self.__resources.setdefault (group_id, ResourceList ())
      resource_list.remove (item_id)

      pymobius.mediator.emit ('app.resource-removed', group_id, item_id)

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief service: app.get-resource
  # @param resource_id: resource ID
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def svc_get_resource (self, resource_id):
    value = None

    if '.' in resource_id:
      group_id, item_id = resource_id.rsplit ('.', 1)
      resource_list = self.__resources.setdefault (group_id, ResourceList ())
      value = resource_list.get (item_id)
  
    return value
    
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief service: app.list-resources
  # @param resource_id: group ID
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def svc_list_resources (self, group_id):
    resource_list = self.__resources.get (group_id) or []

    return list (iter (resource_list))
