"""SQLite parser plugin for iOS Notes database files."""

from dfdatetime import cocoa_time as dfdatetime_cocoa_time

from plaso.containers import events
from plaso.parsers import sqlite
from plaso.parsers.sqlite_plugins import interface


class IOSNotesEventData(events.EventData):
  """iOS Notes event data.

  Attributes:
    creation_time (dfdatetime.DateTimeValues): date and time the note was
        created.
    modification_time (dfdatetime.DateTimeValues): date and time the note was
        last modified.
    snippet (str): snippet of the note.
    title (str): title of the note.
  """

  DATA_TYPE = 'ios:notes:note'

  def __init__(self):
    """Initializes event data."""
    super().__init__(data_type=self.DATA_TYPE)
    self.creation_time = None
    self.modification_time = None
    self.snippet = None
    self.title = None


class IOSNotesPlugin(interface.SQLitePlugin):
  """SQLite parser plugin for iOS Notes database files."""

  NAME = 'ios_notes'
  DATA_FORMAT = 'iOS Notes SQLite database file'

  REQUIRED_STRUCTURE = {
      'ZICCLOUDSYNCINGOBJECT': frozenset([
          'ZCREATIONDATE3', 'ZMODIFICATIONDATE1', 'ZSNIPPET', 'ZTITLE1'])}

  QUERIES = [
      (('SELECT ZCREATIONDATE3, ZMODIFICATIONDATE1, ZSNIPPET, ZTITLE1 '
        'FROM ZICCLOUDSYNCINGOBJECT'), '_ParseNoteRow')]

  SCHEMAS = [{
      'ACHANGE': (
          'CREATE TABLE ACHANGE ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, '
          'Z_OPT INTEGER, ZCHANGETYPE INTEGER, ZENTITY INTEGER, ZENTITYPK '
          'INTEGER, ZTRANSACTIONID INTEGER, ZCOLUMNS BLOB )'),
      'ATRANSACTION': (
          'CREATE TABLE ATRANSACTION ( Z_PK INTEGER PRIMARY KEY, Z_ENT '
          'INTEGER, Z_OPT INTEGER, ZAUTHORTS INTEGER, ZBUNDLEIDTS INTEGER, '
          'ZCONTEXTNAMETS INTEGER, ZPROCESSIDTS INTEGER, ZTIMESTAMP FLOAT, '
          'ZAUTHOR VARCHAR, ZBUNDLEID VARCHAR, ZCONTEXTNAME VARCHAR, '
          'ZPROCESSID VARCHAR, ZQUERYGEN BLOB )'),
      'ATRANSACTIONSTRING': (
          'CREATE TABLE ATRANSACTIONSTRING ( Z_PK INTEGER PRIMARY KEY, Z_ENT '
          'INTEGER, Z_OPT INTEGER, ZNAME VARCHAR )'),
      'ZICCLOUDSTATE': (
          'CREATE TABLE ZICCLOUDSTATE ( Z_PK INTEGER PRIMARY KEY, Z_ENT '
          'INTEGER, Z_OPT INTEGER, ZCURRENTLOCALVERSION INTEGER, ZINCLOUD '
          'INTEGER, ZLATESTVERSIONSYNCEDTOCLOUD INTEGER, ZCLOUDSYNCINGOBJECT '
          'INTEGER, Z2_CLOUDSYNCINGOBJECT INTEGER, ZLOCALVERSIONDATE '
          'TIMESTAMP )'),
      'ZICCLOUDSYNCINGOBJECT': (
          'CREATE TABLE ZICCLOUDSYNCINGOBJECT ( Z_PK INTEGER PRIMARY KEY, '
          'Z_ENT INTEGER, Z_OPT INTEGER, ZCRYPTOITERATIONCOUNT INTEGER, '
          'ZISPASSWORDPROTECTED INTEGER, ZMARKEDFORDELETION INTEGER, '
          'ZMINIMUMSUPPORTEDNOTESVERSION INTEGER, ZNEEDSINITIALFETCHFROMCLOUD '
          'INTEGER, ZNEEDSTOBEFETCHEDFROMCLOUD INTEGER, '
          'ZNEEDSTOSAVEUSERSPECIFICRECORD INTEGER, ZCLOUDSTATE INTEGER, '
          'ZACCOUNT INTEGER, ZCHECKEDFORLOCATION INTEGER, ZFILESIZE INTEGER, '
          'ZHANDWRITINGSUMMARYVERSION INTEGER, ZHASMARKUPDATA INTEGER, '
          'ZIMAGECLASSIFICATIONSUMMARYVERSION INTEGER, ZIMAGEFILTERTYPE '
          'INTEGER, ZNEEDSINITIALRELATIONSHIPSETUP INTEGER, '
          'ZOCRSUMMARYVERSION INTEGER, ZORIENTATION INTEGER, ZSECTION '
          'INTEGER, ZURLEXPIRED INTEGER, ZLOCATION INTEGER, ZMEDIA INTEGER, '
          'ZNOTE INTEGER, ZNOTEUSINGTITLEFORNOTETITLE INTEGER, '
          'ZPARENTATTACHMENT INTEGER, ZAPPEARANCETYPE INTEGER, '
          'ZSCALEWHENDRAWING INTEGER, ZVERSION INTEGER, ZVERSIONOUTOFDATE '
          'INTEGER, ZATTACHMENT INTEGER, ZSTATE INTEGER, ZACCOUNT1 INTEGER, '
          'ZACCOUNT2 INTEGER, ZMENTIONNOTIFICATIONATTEMPTCOUNT INTEGER, '
          'ZMENTIONNOTIFICATIONSTATE INTEGER, ZNOTE1 INTEGER, '
          'ZPARENTATTACHMENT1 INTEGER, ZTYPE INTEGER, ZACCOUNT3 INTEGER, '
          'ZATTACHMENT1 INTEGER, ZATTACHMENTVIEWTYPE INTEGER, ZISPINNED '
          'INTEGER, ZISSYSTEMPAPER INTEGER, ZLEGACYNOTEWASPLAINTEXT INTEGER, '
          'ZNOTEHASCHANGES INTEGER, ZPAPERSTYLETYPE INTEGER, '
          'ZPREFERREDBACKGROUNDTYPE INTEGER, ZACCOUNT4 INTEGER, ZFOLDER '
          'INTEGER, ZNOTEDATA INTEGER, ZTITLESOURCEATTACHMENT INTEGER, '
          'ZISHIDDENNOTECONTAINER INTEGER, ZSORTORDER INTEGER, ZOWNER '
          'INTEGER, ZACCOUNTTYPE INTEGER, ZDIDCHOOSETOMIGRATE INTEGER, '
          'ZDIDFINISHMIGRATION INTEGER, ZDIDMIGRATEONMAC INTEGER, '
          'ZSERVERSIDEUPDATETASKFAILURECOUNT INTEGER, ZSTOREDATASEPARATELY '
          'INTEGER, ZACCOUNTDATA INTEGER, ZCUSTOMNOTESORTTYPEVALUE INTEGER, '
          'ZFOLDERTYPE INTEGER, ZIMPORTEDFROMLEGACY INTEGER, ZACCOUNT5 '
          'INTEGER, ZPARENT INTEGER, ZCREATIONDATE TIMESTAMP, '
          'ZCROPPINGQUADBOTTOMLEFTX FLOAT, ZCROPPINGQUADBOTTOMLEFTY FLOAT, '
          'ZCROPPINGQUADBOTTOMRIGHTX FLOAT, ZCROPPINGQUADBOTTOMRIGHTY FLOAT, '
          'ZCROPPINGQUADTOPLEFTX FLOAT, ZCROPPINGQUADTOPLEFTY FLOAT, '
          'ZCROPPINGQUADTOPRIGHTX FLOAT, ZCROPPINGQUADTOPRIGHTY FLOAT, '
          'ZDURATION FLOAT, ZMODIFICATIONDATE TIMESTAMP, ZORIGINX FLOAT, '
          'ZORIGINY FLOAT, ZPREVIEWUPDATEDATE TIMESTAMP, ZSIZEHEIGHT FLOAT, '
          'ZSIZEWIDTH FLOAT, ZHEIGHT FLOAT, ZMODIFIEDDATE TIMESTAMP, ZSCALE '
          'FLOAT, ZWIDTH FLOAT, ZSTATEMODIFICATIONDATE TIMESTAMP, '
          'ZCREATIONDATE1 TIMESTAMP, ZCREATIONDATE2 TIMESTAMP, '
          'ZMODIFICATIONDATEATIMPORT TIMESTAMP, ZCREATIONDATE3 TIMESTAMP, '
          'ZFOLDERMODIFICATIONDATE TIMESTAMP, '
          'ZLASTACTIVITYRECENTUPDATESVIEWEDDATE TIMESTAMP, '
          'ZLASTACTIVITYSUMMARYVIEWEDDATE TIMESTAMP, '
          'ZLASTATTRIBUTIONSVIEWEDDATE TIMESTAMP, ZLASTNOTIFIEDDATE '
          'TIMESTAMP, ZLASTOPENEDDATE TIMESTAMP, ZLASTVIEWEDMODIFICATIONDATE '
          'TIMESTAMP, ZLEGACYMODIFICATIONDATEATIMPORT TIMESTAMP, '
          'ZMODIFICATIONDATE1 TIMESTAMP, ZCUSTOMNOTESORTTYPEMODIFICATIONDATE '
          'TIMESTAMP, ZDATEFORLASTTITLEMODIFICATION TIMESTAMP, '
          'ZPARENTMODIFICATIONDATE TIMESTAMP, ZIDENTIFIER VARCHAR, '
          'ZPASSWORDHINT VARCHAR, ZZONEOWNERNAME VARCHAR, '
          'ZADDITIONALINDEXABLETEXT VARCHAR, ZFALLBACKSUBTITLEIOS VARCHAR, '
          'ZFALLBACKSUBTITLEMAC VARCHAR, ZFALLBACKTITLE VARCHAR, '
          'ZHANDWRITINGSUMMARY VARCHAR, ZIMAGECLASSIFICATIONSUMMARY VARCHAR, '
          'ZOCRSUMMARY VARCHAR, ZREMOTEFILEURLSTRING VARCHAR, ZSUMMARY '
          'VARCHAR, ZTITLE VARCHAR, ZTYPEUTI VARCHAR, ZURLSTRING VARCHAR, '
          'ZUSERTITLE VARCHAR, ZDEVICEIDENTIFIER VARCHAR, ZDISPLAYTEXT '
          'VARCHAR, ZSTANDARDIZEDCONTENT VARCHAR, ZALTTEXT VARCHAR, '
          'ZTOKENCONTENTIDENTIFIER VARCHAR, ZTYPEUTI1 VARCHAR, '
          'ZCONTENTHASHATIMPORT VARCHAR, ZFILENAME VARCHAR, '
          'ZLEGACYCONTENTHASHATIMPORT VARCHAR, ZLEGACYIMPORTDEVICEIDENTIFIER '
          'VARCHAR, ZLEGACYMANAGEDOBJECTIDURIREPRESENTATION VARCHAR, '
          'ZSELECTEDINKCOLORSTRING VARCHAR, ZSELECTEDINKIDENTIFIER VARCHAR, '
          'ZSNIPPET VARCHAR, ZTHUMBNAILATTACHMENTIDENTIFIER VARCHAR, ZTITLE1 '
          'VARCHAR, ZACCOUNTNAMEFORACCOUNTLISTSORTING VARCHAR, '
          'ZNESTEDTITLEFORSORTING VARCHAR, ZNAME VARCHAR, '
          'ZSERVERSIDEUPDATETASKLASTATTEMPTEDBUILD VARCHAR, '
          'ZSERVERSIDEUPDATETASKLASTATTEMPTEDVERSION VARCHAR, '
          'ZSERVERSIDEUPDATETASKLASTCOMPLETEDBUILD VARCHAR, '
          'ZSERVERSIDEUPDATETASKLASTCOMPLETEDVERSION VARCHAR, ZUSERRECORDNAME '
          'VARCHAR, ZSMARTFOLDERQUERYJSON VARCHAR, ZTITLE2 VARCHAR, '
          'ZPAPERASSETSURL VARCHAR, ZPAPERDATABASEURL VARCHAR, '
          'ZREPLICAIDTOBUNDLEIDENTIFIER BLOB, ZACTIVITYEVENTSDATA BLOB, '
          'ZASSETCRYPTOINITIALIZATIONVECTOR BLOB, ZASSETCRYPTOTAG BLOB, '
          'ZCRYPTOINITIALIZATIONVECTOR BLOB, ZCRYPTOSALT BLOB, ZCRYPTOTAG '
          'BLOB, ZCRYPTOWRAPPEDKEY BLOB, ZENCRYPTEDVALUESJSON BLOB, '
          'ZREPLICAIDTONOTESVERSIONDATA BLOB, ZSERVERRECORDDATA BLOB, '
          'ZSERVERSHAREDATA BLOB, ZUNAPPLIEDENCRYPTEDRECORD BLOB, '
          'ZUSERSPECIFICSERVERRECORDDATA BLOB, ZMERGEABLEDATA BLOB, '
          'ZFALLBACKIMAGECRYPTOINITIALIZATIONVECTOR BLOB, '
          'ZFALLBACKIMAGECRYPTOTAG BLOB, ZLINKPRESENTATIONARCHIVEDMETADATA '
          'BLOB, ZMARKUPMODELDATA BLOB, ZMERGEABLEDATA1 BLOB, ZMETADATADATA '
          'BLOB, ZSYNAPSEDATA BLOB, ZCRYPTOMETADATAINITIALIZATIONVECTOR BLOB, '
          'ZCRYPTOMETADATATAG BLOB, ZENCRYPTEDMETADATA BLOB, ZMETADATA BLOB, '
          'ZLASTNOTIFIEDTIMESTAMPDATA BLOB, ZLASTVIEWEDTIMESTAMPDATA BLOB, '
          'ZREPLICAIDTOUSERIDDICTDATA BLOB, ZCRYPTOVERIFIER BLOB, '
          'ZSERVERSIDEUPDATETASKCONTINUATIONTOKEN BLOB, ZMERGEABLEDATA2 BLOB '
          ')'),
      'ZICLOCATION': (
          'CREATE TABLE ZICLOCATION ( Z_PK INTEGER PRIMARY KEY, Z_ENT '
          'INTEGER, Z_OPT INTEGER, ZPLACEUPDATED INTEGER, ZATTACHMENT '
          'INTEGER, ZLATITUDE FLOAT, ZLONGITUDE FLOAT, ZPLACEMARKDATA BLOB )'),
      'ZICNOTEDATA': (
          'CREATE TABLE ZICNOTEDATA ( Z_PK INTEGER PRIMARY KEY, Z_ENT '
          'INTEGER, Z_OPT INTEGER, ZNOTE INTEGER, ZCRYPTOINITIALIZATIONVECTOR '
          'BLOB, ZCRYPTOTAG BLOB, ZDATA BLOB )'),
      'ZICSERVERCHANGETOKEN': (
          'CREATE TABLE ZICSERVERCHANGETOKEN ( Z_PK INTEGER PRIMARY KEY, '
          'Z_ENT INTEGER, Z_OPT INTEGER, ZDATABASESCOPE INTEGER, ZACCOUNT '
          'INTEGER, ZOWNERNAME VARCHAR, ZZONENAME VARCHAR, '
          'ZCKSERVERCHANGETOKENDATA BLOB )'),
      'Z_METADATA': (
          'CREATE TABLE Z_METADATA (Z_VERSION INTEGER PRIMARY KEY, Z_UUID '
          'VARCHAR(255), Z_PLIST BLOB)'),
      'Z_MODELCACHE': (
          'CREATE TABLE Z_MODELCACHE (Z_CONTENT BLOB)'),
      'Z_PRIMARYKEY': (
          'CREATE TABLE Z_PRIMARYKEY (Z_ENT INTEGER PRIMARY KEY, Z_NAME '
          'VARCHAR, Z_SUPER INTEGER, Z_MAX INTEGER)')}]

  def _GetDateTimeRowValue(self, query_hash, row, value_name):
    """Retrieves a date and time value from the row.

    Args:
      query_hash (int): hash of the query, that uniquely
        identifies the query that produced the row.
      row (sqlite3.Row): row.
      value_name (str): name of the value.

    Returns:
      dfdatetime.CocoaTime: date and time value or None if not available.
    """
    timestamp = self._GetRowValue(query_hash, row, value_name)
    if timestamp is None:
      return None

    return dfdatetime_cocoa_time.CocoaTime(timestamp=timestamp)

  def _ParseNoteRow(self, parser_mediator, query, row, **unused_kwargs):
    """Parses a note row.

    Args:
      parser_mediator (ParserMediator): mediates interactions between
          parsers and other components, such as storage and dfVFS.
      query (str): query that created the row.
      row (sqlite3.Row): row.
    """
    query_hash = hash(query)

    event_data = IOSNotesEventData()
    event_data.creation_time = self._GetDateTimeRowValue(
        query_hash, row, 'ZCREATIONDATE3')
    event_data.modification_time = self._GetDateTimeRowValue(
        query_hash, row, 'ZMODIFICATIONDATE1')
    event_data.title = self._GetRowValue(query_hash, row, 'ZTITLE1')
    event_data.snippet = self._GetRowValue(query_hash, row, 'ZSNIPPET')

    parser_mediator.ProduceEventData(event_data)


sqlite.SQLiteParser.RegisterPlugin(IOSNotesPlugin)
