# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Mobius Forensic Toolkit
# Copyright (C) 2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018 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 inspect
import datetime
import json
import pymobius.deprecated
import pymobius.xml

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief JSON encoder helper function
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def json_encoder (obj):

  if isinstance (obj, datetime.datetime):
    data = {
            'class' : 'datetime.datetime',
            'data' : [obj.year, obj.month, obj.day, obj.hour, obj.minute, obj.second]
           }

  elif isinstance (obj, (pymobius.xml.PyObject, pymobius.deprecated.Object, object)):
    attrs = {}

    for name, value in inspect.getmembers (obj):
      if not callable (value) and not name.startswith ('__'):
        attrs[name] = value

    classname = obj.__class__.__module__ + '.' + obj.__class__.__name__
    data = {'class' : classname, 'attrs' : attrs}

  else:
    data = None

  return data

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief JSON decoder helper function
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def json_decoder (dct):
  classname = dct.pop ('class', None)
    
  if classname == 'datetime.datetime':
    args = dct.pop ('data', [])
    data = datetime.datetime (*args)

  elif classname == 'pymobius.xml.PyObject':
    data = pymobius.xml.PyObject ()
    attrs = dct.pop ('attrs', {})
    
    for name, value in attrs.iteritems ():
      setattr (data, name, value)

  elif classname == 'pymobius.deprecated.Object':
    data = pymobius.deprecated.Object ()
    attrs = dct.pop ('attrs', {})
    
    for name, value in attrs.iteritems ():
      data._initattr (name, value)

  elif classname:
    data = pymobius.xml.PyObject ()
    attrs = dct.pop ('attrs', {})
    
    for name, value in attrs.iteritems ():
      setattr (data, name, value)

  else:
    data = dct

  return data

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief Serialize objects as JSON string
# @param obj Any python object
# @return JSON string
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def serialize (obj):
  return json.dumps (obj, sort_keys=True, separators=(',',':'), default=json_encoder)

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief Unserialize JSON string as object
# @param text JSON string
# @return obj
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def unserialize (text):
  return json.loads (text, encoding='utf-8', object_hook=json_decoder)
