"""SQLite parser plugin for iOS accounts (Accounts3.db) database files."""

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


class IOSAccountsEventData(events.EventData):
    """iOS accounts event data.

    Attributes:
      account_type (str): account type.
      creation_time (dfdatetime.DateTimeValues): date and time the account
          was created.
      identifier (str): identifier.
      owning_bundle_identifier (str): owning bundle identifier of the
          application managing the account.
      username (str): user name.
    """

    DATA_TYPE = "ios:accounts:entry"

    def __init__(self):
        """Initializes event data."""
        super().__init__(data_type=self.DATA_TYPE)
        self.account_type = None
        self.creation_time = None
        self.identifier = None
        self.owning_bundle_identifier = None
        self.username = None


class IOSAccountsPlugin(interface.SQLitePlugin):
    """SQLite parser plugin for iOS accounts (Accounts3.db) database files."""

    NAME = "ios_accounts"
    DATA_FORMAT = "iOS accounts SQLite database (Accounts3.db) file"

    REQUIRED_STRUCTURE = {
        "ZACCOUNT": frozenset(
            ["ZACCOUNTTYPE", "ZDATE", "ZUSERNAME", "ZIDENTIFIER", "ZOWNINGBUNDLEID"]
        ),
        "ZACCOUNTTYPE": frozenset(["Z_PK", "ZACCOUNTTYPEDESCRIPTION"]),
    }

    QUERIES = [
        (
            (
                "SELECT ZACCOUNT.ZDATE, ZACCOUNTTYPE.ZACCOUNTTYPEDESCRIPTION, "
                "ZACCOUNT.ZUSERNAME, ZACCOUNT.ZIDENTIFIER, ZACCOUNT.ZOWNINGBUNDLEID "
                "FROM ZACCOUNT LEFT JOIN ZACCOUNTTYPE "
                "ON ZACCOUNT.ZACCOUNTTYPE = ZACCOUNTTYPE.Z_PK"
            ),
            "ParseAccountRow",
        )
    ]

    SCHEMAS = [
        {
            "ZACCESSOPTIONSKEY": (
                "CREATE TABLE ZACCESSOPTIONSKEY ( Z_PK INTEGER PRIMARY KEY, Z_ENT "
                "INTEGER, Z_OPT INTEGER, ZNAME VARCHAR )"
            ),
            "ZACCOUNT": (
                "CREATE TABLE ZACCOUNT ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, "
                "Z_OPT INTEGER, ZACTIVE INTEGER, ZAUTHENTICATED INTEGER, "
                "ZSUPPORTSAUTHENTICATION INTEGER, ZVISIBLE INTEGER, ZACCOUNTTYPE "
                "INTEGER, ZPARENTACCOUNT INTEGER, ZDATE TIMESTAMP, "
                "ZLASTCREDENTIALRENEWALREJECTIONDATE TIMESTAMP, ZACCOUNTDESCRIPTION "
                "VARCHAR, ZAUTHENTICATIONTYPE VARCHAR, ZCREDENTIALTYPE VARCHAR, "
                "ZIDENTIFIER VARCHAR, ZOWNINGBUNDLEID VARCHAR, ZUSERNAME VARCHAR, "
                "ZDATACLASSPROPERTIES BLOB )"
            ),
            "ZACCOUNTPROPERTY": (
                "CREATE TABLE ZACCOUNTPROPERTY ( Z_PK INTEGER PRIMARY KEY, Z_ENT "
                "INTEGER, Z_OPT INTEGER, ZOWNER INTEGER, ZKEY VARCHAR, ZVALUE BLOB "
                ")"
            ),
            "ZACCOUNTTYPE": (
                "CREATE TABLE ZACCOUNTTYPE ( Z_PK INTEGER PRIMARY KEY, Z_ENT "
                "INTEGER, Z_OPT INTEGER, ZENCRYPTACCOUNTPROPERTIES INTEGER, "
                "ZOBSOLETE INTEGER, ZSUPPORTSAUTHENTICATION INTEGER, "
                "ZSUPPORTSMULTIPLEACCOUNTS INTEGER, ZVISIBILITY INTEGER, "
                "ZACCOUNTTYPEDESCRIPTION VARCHAR, ZCREDENTIALPROTECTIONPOLICY "
                "VARCHAR, ZCREDENTIALTYPE VARCHAR, ZIDENTIFIER VARCHAR, "
                "ZOWNINGBUNDLEID VARCHAR )"
            ),
            "ZAUTHORIZATION": (
                "CREATE TABLE ZAUTHORIZATION ( Z_PK INTEGER PRIMARY KEY, Z_ENT "
                "INTEGER, Z_OPT INTEGER, ZACCOUNTTYPE INTEGER, ZBUNDLEID VARCHAR, "
                "ZGRANTEDPERMISSIONS VARCHAR, ZOPTIONS BLOB )"
            ),
            "ZCREDENTIALITEM": (
                "CREATE TABLE ZCREDENTIALITEM ( Z_PK INTEGER PRIMARY KEY, Z_ENT "
                "INTEGER, Z_OPT INTEGER, ZPERSISTENT INTEGER, ZEXPIRATIONDATE "
                "TIMESTAMP, ZACCOUNTIDENTIFIER VARCHAR, ZSERVICENAME VARCHAR )"
            ),
            "ZDATACLASS": (
                "CREATE TABLE ZDATACLASS ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, "
                "Z_OPT INTEGER, ZNAME BLOB )"
            ),
            "Z_1OWNINGACCOUNTTYPES": (
                "CREATE TABLE Z_1OWNINGACCOUNTTYPES ( Z_1ACCESSKEYS INTEGER, "
                "Z_4OWNINGACCOUNTTYPES INTEGER, PRIMARY KEY (Z_1ACCESSKEYS, "
                "Z_4OWNINGACCOUNTTYPES) )"
            ),
            "Z_2ENABLEDDATACLASSES": (
                "CREATE TABLE Z_2ENABLEDDATACLASSES ( Z_2ENABLEDACCOUNTS INTEGER, "
                "Z_7ENABLEDDATACLASSES INTEGER, PRIMARY KEY (Z_2ENABLEDACCOUNTS, "
                "Z_7ENABLEDDATACLASSES) )"
            ),
            "Z_2PROVISIONEDDATACLASSES": (
                "CREATE TABLE Z_2PROVISIONEDDATACLASSES ( Z_2PROVISIONEDACCOUNTS "
                "INTEGER, Z_7PROVISIONEDDATACLASSES INTEGER, PRIMARY KEY "
                "(Z_2PROVISIONEDACCOUNTS, Z_7PROVISIONEDDATACLASSES) )"
            ),
            "Z_4SUPPORTEDDATACLASSES": (
                "CREATE TABLE Z_4SUPPORTEDDATACLASSES ( Z_4SUPPORTEDTYPES INTEGER, "
                "Z_7SUPPORTEDDATACLASSES INTEGER, PRIMARY KEY (Z_4SUPPORTEDTYPES, "
                "Z_7SUPPORTEDDATACLASSES) )"
            ),
            "Z_4SYNCABLEDATACLASSES": (
                "CREATE TABLE Z_4SYNCABLEDATACLASSES ( Z_4SYNCABLETYPES INTEGER, "
                "Z_7SYNCABLEDATACLASSES INTEGER, PRIMARY KEY (Z_4SYNCABLETYPES, "
                "Z_7SYNCABLEDATACLASSES) )"
            ),
            "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)"
            ),
        }
    ]

    REQUIRES_SCHEMA_MATCH = False

    # pylint: disable=unused-argument
    def ParseAccountRow(self, parser_mediator, query, row, **unused_kwargs):
        """Parses an account 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 = IOSAccountsEventData()
        event_data.account_type = self._GetRowValue(
            query_hash, row, "ZACCOUNTTYPEDESCRIPTION"
        )
        event_data.creation_time = self._GetCocoaTimeRowValue(query_hash, row, "ZDATE")
        event_data.identifier = self._GetRowValue(query_hash, row, "ZIDENTIFIER")
        event_data.owning_bundle_identifier = self._GetRowValue(
            query_hash, row, "ZOWNINGBUNDLEID"
        )
        event_data.username = self._GetRowValue(query_hash, row, "ZUSERNAME")

        parser_mediator.ProduceEventData(event_data)


sqlite.SQLiteParser.RegisterPlugin(IOSAccountsPlugin)
