package com.ustadmobile.core.db.dao;

import android.database.Cursor;
import android.os.CancellationSignal;
import androidx.paging.DataSource;
import androidx.room.CoroutinesRoom;
import androidx.room.EntityDeletionOrUpdateAdapter;
import androidx.room.EntityInsertionAdapter;
import androidx.room.RoomDatabase;
import androidx.room.RoomSQLiteQuery;
import androidx.room.SharedSQLiteStatement;
import androidx.room.paging.LimitOffsetDataSource;
import androidx.room.util.CursorUtil;
import androidx.room.util.DBUtil;
import androidx.room.util.StringUtil;
import androidx.sqlite.db.SupportSQLiteStatement;
import com.ustadmobile.lib.db.entities.VerbDisplay;
import com.ustadmobile.lib.db.entities.VerbEntity;
import java.lang.Class;
import java.lang.Exception;
import java.lang.Integer;
import java.lang.Long;
import java.lang.Object;
import java.lang.Override;
import java.lang.String;
import java.lang.StringBuilder;
import java.lang.SuppressWarnings;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import kotlin.Unit;
import kotlin.coroutines.Continuation;

@SuppressWarnings({"unchecked", "deprecation"})
public final class VerbDao_Impl extends VerbDao {
  private final RoomDatabase __db;

  private final EntityInsertionAdapter<VerbEntity> __insertionAdapterOfVerbEntity;

  private final EntityInsertionAdapter<VerbEntity> __insertionAdapterOfVerbEntity_1;

  private final EntityDeletionOrUpdateAdapter<VerbEntity> __updateAdapterOfVerbEntity;

  private final SharedSQLiteStatement __preparedStmtOfReplicateOnNewNode;

  private final SharedSQLiteStatement __preparedStmtOfReplicateOnChange;

  public VerbDao_Impl(RoomDatabase __db) {
    this.__db = __db;
    this.__insertionAdapterOfVerbEntity = new EntityInsertionAdapter<VerbEntity>(__db) {
      @Override
      public String createQuery() {
        return "INSERT OR ABORT INTO `VerbEntity` (`verbUid`,`urlId`,`verbInActive`,`verbMasterChangeSeqNum`,`verbLocalChangeSeqNum`,`verbLastChangedBy`,`verbLct`) VALUES (nullif(?, 0),?,?,?,?,?,?)";
      }

      @Override
      public void bind(SupportSQLiteStatement stmt, VerbEntity value) {
        stmt.bindLong(1, value.getVerbUid());
        if (value.getUrlId() == null) {
          stmt.bindNull(2);
        } else {
          stmt.bindString(2, value.getUrlId());
        }
        final int _tmp = value.getVerbInActive() ? 1 : 0;
        stmt.bindLong(3, _tmp);
        stmt.bindLong(4, value.getVerbMasterChangeSeqNum());
        stmt.bindLong(5, value.getVerbLocalChangeSeqNum());
        stmt.bindLong(6, value.getVerbLastChangedBy());
        stmt.bindLong(7, value.getVerbLct());
      }
    };
    this.__insertionAdapterOfVerbEntity_1 = new EntityInsertionAdapter<VerbEntity>(__db) {
      @Override
      public String createQuery() {
        return "INSERT OR REPLACE INTO `VerbEntity` (`verbUid`,`urlId`,`verbInActive`,`verbMasterChangeSeqNum`,`verbLocalChangeSeqNum`,`verbLastChangedBy`,`verbLct`) VALUES (nullif(?, 0),?,?,?,?,?,?)";
      }

      @Override
      public void bind(SupportSQLiteStatement stmt, VerbEntity value) {
        stmt.bindLong(1, value.getVerbUid());
        if (value.getUrlId() == null) {
          stmt.bindNull(2);
        } else {
          stmt.bindString(2, value.getUrlId());
        }
        final int _tmp = value.getVerbInActive() ? 1 : 0;
        stmt.bindLong(3, _tmp);
        stmt.bindLong(4, value.getVerbMasterChangeSeqNum());
        stmt.bindLong(5, value.getVerbLocalChangeSeqNum());
        stmt.bindLong(6, value.getVerbLastChangedBy());
        stmt.bindLong(7, value.getVerbLct());
      }
    };
    this.__updateAdapterOfVerbEntity = new EntityDeletionOrUpdateAdapter<VerbEntity>(__db) {
      @Override
      public String createQuery() {
        return "UPDATE OR ABORT `VerbEntity` SET `verbUid` = ?,`urlId` = ?,`verbInActive` = ?,`verbMasterChangeSeqNum` = ?,`verbLocalChangeSeqNum` = ?,`verbLastChangedBy` = ?,`verbLct` = ? WHERE `verbUid` = ?";
      }

      @Override
      public void bind(SupportSQLiteStatement stmt, VerbEntity value) {
        stmt.bindLong(1, value.getVerbUid());
        if (value.getUrlId() == null) {
          stmt.bindNull(2);
        } else {
          stmt.bindString(2, value.getUrlId());
        }
        final int _tmp = value.getVerbInActive() ? 1 : 0;
        stmt.bindLong(3, _tmp);
        stmt.bindLong(4, value.getVerbMasterChangeSeqNum());
        stmt.bindLong(5, value.getVerbLocalChangeSeqNum());
        stmt.bindLong(6, value.getVerbLastChangedBy());
        stmt.bindLong(7, value.getVerbLct());
        stmt.bindLong(8, value.getVerbUid());
      }
    };
    this.__preparedStmtOfReplicateOnNewNode = new SharedSQLiteStatement(__db) {
      @Override
      public String createQuery() {
        final String _query = "\n"
                + "     REPLACE INTO VerbEntityReplicate(vePk, veDestination)\n"
                + "      SELECT DISTINCT VerbEntity.verbUid AS vePk,\n"
                + "             ? AS veDestination\n"
                + "        FROM VerbEntity\n"
                + "       WHERE VerbEntity.verbLct != COALESCE(\n"
                + "             (SELECT veVersionId\n"
                + "                FROM VerbEntityReplicate\n"
                + "               WHERE vePk = VerbEntity.verbUid\n"
                + "                 AND veDestination = ?), 0) \n"
                + "      /*psql ON CONFLICT(vePk, veDestination) DO UPDATE\n"
                + "             SET vePending = true\n"
                + "      */       \n"
                + "    ";
        return _query;
      }
    };
    this.__preparedStmtOfReplicateOnChange = new SharedSQLiteStatement(__db) {
      @Override
      public String createQuery() {
        final String _query = "\n"
                + "    REPLACE INTO VerbEntityReplicate(vePk, veDestination)\n"
                + "    SELECT DISTINCT VerbEntity.verbUid AS veUid,\n"
                + "         UserSession.usClientNodeId AS veDestination\n"
                + "    FROM ChangeLog\n"
                + "         JOIN VerbEntity\n"
                + "             ON ChangeLog.chTableId = 62\n"
                + "                AND ChangeLog.chEntityPk = VerbEntity.verbUid\n"
                + "         JOIN UserSession ON UserSession.usStatus = 1\n"
                + "    WHERE UserSession.usClientNodeId != (\n"
                + "         SELECT nodeClientId \n"
                + "           FROM SyncNode\n"
                + "          LIMIT 1)\n"
                + "     AND VerbEntity.verbLct != COALESCE(\n"
                + "         (SELECT veVersionId\n"
                + "            FROM VerbEntityReplicate\n"
                + "           WHERE vePk = VerbEntity.verbUid\n"
                + "             AND veDestination = UserSession.usClientNodeId), 0)\n"
                + "    /*psql ON CONFLICT(vePk, veDestination) DO UPDATE\n"
                + "     SET vePending = true\n"
                + "    */               \n"
                + "    ";
        return _query;
      }
    };
  }

  @Override
  public long insert(final VerbEntity entity) {
    __db.assertNotSuspendingTransaction();
    __db.beginTransaction();
    try {
      long _result = __insertionAdapterOfVerbEntity.insertAndReturnId(entity);
      __db.setTransactionSuccessful();
      return _result;
    } finally {
      __db.endTransaction();
    }
  }

  @Override
  public Object insertAsync(final VerbEntity entity,
      final Continuation<? super Long> continuation) {
    return CoroutinesRoom.execute(__db, true, new Callable<Long>() {
      @Override
      public Long call() throws Exception {
        __db.beginTransaction();
        try {
          long _result = __insertionAdapterOfVerbEntity.insertAndReturnId(entity);
          __db.setTransactionSuccessful();
          return _result;
        } finally {
          __db.endTransaction();
        }
      }
    }, continuation);
  }

  @Override
  public void insertList(final List<? extends VerbEntity> entityList) {
    __db.assertNotSuspendingTransaction();
    __db.beginTransaction();
    try {
      __insertionAdapterOfVerbEntity.insert(entityList);
      __db.setTransactionSuccessful();
    } finally {
      __db.endTransaction();
    }
  }

  @Override
  public Object replaceList(final List<VerbEntity> entityList,
      final Continuation<? super Unit> continuation) {
    return CoroutinesRoom.execute(__db, true, new Callable<Unit>() {
      @Override
      public Unit call() throws Exception {
        __db.beginTransaction();
        try {
          __insertionAdapterOfVerbEntity_1.insert(entityList);
          __db.setTransactionSuccessful();
          return Unit.INSTANCE;
        } finally {
          __db.endTransaction();
        }
      }
    }, continuation);
  }

  @Override
  public void updateList(final List<? extends VerbEntity> entityList) {
    __db.assertNotSuspendingTransaction();
    __db.beginTransaction();
    try {
      __updateAdapterOfVerbEntity.handleMultiple(entityList);
      __db.setTransactionSuccessful();
    } finally {
      __db.endTransaction();
    }
  }

  @Override
  public void update(final VerbEntity entity) {
    __db.assertNotSuspendingTransaction();
    __db.beginTransaction();
    try {
      __updateAdapterOfVerbEntity.handle(entity);
      __db.setTransactionSuccessful();
    } finally {
      __db.endTransaction();
    }
  }

  @Override
  public Object replicateOnNewNode(final long newNodeId,
      final Continuation<? super Unit> continuation) {
    return CoroutinesRoom.execute(__db, true, new Callable<Unit>() {
      @Override
      public Unit call() throws Exception {
        final SupportSQLiteStatement _stmt = __preparedStmtOfReplicateOnNewNode.acquire();
        int _argIndex = 1;
        _stmt.bindLong(_argIndex, newNodeId);
        _argIndex = 2;
        _stmt.bindLong(_argIndex, newNodeId);
        __db.beginTransaction();
        try {
          _stmt.executeInsert();
          __db.setTransactionSuccessful();
          return Unit.INSTANCE;
        } finally {
          __db.endTransaction();
          __preparedStmtOfReplicateOnNewNode.release(_stmt);
        }
      }
    }, continuation);
  }

  @Override
  public Object replicateOnChange(final Continuation<? super Unit> continuation) {
    return CoroutinesRoom.execute(__db, true, new Callable<Unit>() {
      @Override
      public Unit call() throws Exception {
        final SupportSQLiteStatement _stmt = __preparedStmtOfReplicateOnChange.acquire();
        __db.beginTransaction();
        try {
          _stmt.executeInsert();
          __db.setTransactionSuccessful();
          return Unit.INSTANCE;
        } finally {
          __db.endTransaction();
          __preparedStmtOfReplicateOnChange.release(_stmt);
        }
      }
    }, continuation);
  }

  @Override
  public VerbEntity findByUrl(final String urlId) {
    final String _sql = "SELECT * FROM VerbEntity WHERE urlId = ?";
    final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 1);
    int _argIndex = 1;
    if (urlId == null) {
      _statement.bindNull(_argIndex);
    } else {
      _statement.bindString(_argIndex, urlId);
    }
    __db.assertNotSuspendingTransaction();
    final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
    try {
      final int _cursorIndexOfVerbUid = CursorUtil.getColumnIndexOrThrow(_cursor, "verbUid");
      final int _cursorIndexOfUrlId = CursorUtil.getColumnIndexOrThrow(_cursor, "urlId");
      final int _cursorIndexOfVerbInActive = CursorUtil.getColumnIndexOrThrow(_cursor, "verbInActive");
      final int _cursorIndexOfVerbMasterChangeSeqNum = CursorUtil.getColumnIndexOrThrow(_cursor, "verbMasterChangeSeqNum");
      final int _cursorIndexOfVerbLocalChangeSeqNum = CursorUtil.getColumnIndexOrThrow(_cursor, "verbLocalChangeSeqNum");
      final int _cursorIndexOfVerbLastChangedBy = CursorUtil.getColumnIndexOrThrow(_cursor, "verbLastChangedBy");
      final int _cursorIndexOfVerbLct = CursorUtil.getColumnIndexOrThrow(_cursor, "verbLct");
      final VerbEntity _result;
      if(_cursor.moveToFirst()) {
        _result = new VerbEntity();
        final long _tmpVerbUid;
        _tmpVerbUid = _cursor.getLong(_cursorIndexOfVerbUid);
        _result.setVerbUid(_tmpVerbUid);
        final String _tmpUrlId;
        if (_cursor.isNull(_cursorIndexOfUrlId)) {
          _tmpUrlId = null;
        } else {
          _tmpUrlId = _cursor.getString(_cursorIndexOfUrlId);
        }
        _result.setUrlId(_tmpUrlId);
        final boolean _tmpVerbInActive;
        final int _tmp;
        _tmp = _cursor.getInt(_cursorIndexOfVerbInActive);
        _tmpVerbInActive = _tmp != 0;
        _result.setVerbInActive(_tmpVerbInActive);
        final long _tmpVerbMasterChangeSeqNum;
        _tmpVerbMasterChangeSeqNum = _cursor.getLong(_cursorIndexOfVerbMasterChangeSeqNum);
        _result.setVerbMasterChangeSeqNum(_tmpVerbMasterChangeSeqNum);
        final long _tmpVerbLocalChangeSeqNum;
        _tmpVerbLocalChangeSeqNum = _cursor.getLong(_cursorIndexOfVerbLocalChangeSeqNum);
        _result.setVerbLocalChangeSeqNum(_tmpVerbLocalChangeSeqNum);
        final int _tmpVerbLastChangedBy;
        _tmpVerbLastChangedBy = _cursor.getInt(_cursorIndexOfVerbLastChangedBy);
        _result.setVerbLastChangedBy(_tmpVerbLastChangedBy);
        final long _tmpVerbLct;
        _tmpVerbLct = _cursor.getLong(_cursorIndexOfVerbLct);
        _result.setVerbLct(_tmpVerbLct);
      } else {
        _result = null;
      }
      return _result;
    } finally {
      _cursor.close();
      _statement.release();
    }
  }

  @Override
  public Object findByUidList(final List<Long> uidList,
      final Continuation<? super List<Long>> continuation) {
    StringBuilder _stringBuilder = StringUtil.newStringBuilder();
    _stringBuilder.append("SELECT verbUid FROM VerbEntity WHERE verbUid IN (");
    final int _inputSize = uidList.size();
    StringUtil.appendPlaceholders(_stringBuilder, _inputSize);
    _stringBuilder.append(")");
    final String _sql = _stringBuilder.toString();
    final int _argCount = 0 + _inputSize;
    final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, _argCount);
    int _argIndex = 1;
    for (long _item : uidList) {
      _statement.bindLong(_argIndex, _item);
      _argIndex ++;
    }
    final CancellationSignal _cancellationSignal = DBUtil.createCancellationSignal();
    return CoroutinesRoom.execute(__db, false, _cancellationSignal, new Callable<List<Long>>() {
      @Override
      public List<Long> call() throws Exception {
        final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
        try {
          final List<Long> _result = new ArrayList<Long>(_cursor.getCount());
          while(_cursor.moveToNext()) {
            final Long _item_1;
            _item_1 = _cursor.getLong(0);
            _result.add(_item_1);
          }
          return _result;
        } finally {
          _cursor.close();
          _statement.release();
        }
      }
    }, continuation);
  }

  @Override
  public List<VerbDisplay> findAllVerbsAscList(final List<Long> uidList) {
    StringBuilder _stringBuilder = StringUtil.newStringBuilder();
    _stringBuilder.append("SELECT VerbEntity.verbUid, VerbEntity.urlId, XLangMapEntry.valueLangMap AS display");
    _stringBuilder.append("\n");
    _stringBuilder.append("        FROM VerbEntity LEFT JOIN XLangMapEntry on XLangMapEntry.verbLangMapUid = VerbEntity.verbUid WHERE ");
    _stringBuilder.append("\n");
    _stringBuilder.append("         XLangMapEntry.verbLangMapUid NOT IN (");
    final int _inputSize = uidList.size();
    StringUtil.appendPlaceholders(_stringBuilder, _inputSize);
    _stringBuilder.append(")");
    final String _sql = _stringBuilder.toString();
    final int _argCount = 0 + _inputSize;
    final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, _argCount);
    int _argIndex = 1;
    for (long _item : uidList) {
      _statement.bindLong(_argIndex, _item);
      _argIndex ++;
    }
    __db.assertNotSuspendingTransaction();
    final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
    try {
      final int _cursorIndexOfVerbUid = 0;
      final int _cursorIndexOfUrlId = 1;
      final int _cursorIndexOfDisplay = 2;
      final List<VerbDisplay> _result = new ArrayList<VerbDisplay>(_cursor.getCount());
      while(_cursor.moveToNext()) {
        final VerbDisplay _item_1;
        _item_1 = new VerbDisplay();
        final long _tmpVerbUid;
        _tmpVerbUid = _cursor.getLong(_cursorIndexOfVerbUid);
        _item_1.setVerbUid(_tmpVerbUid);
        final String _tmpUrlId;
        if (_cursor.isNull(_cursorIndexOfUrlId)) {
          _tmpUrlId = null;
        } else {
          _tmpUrlId = _cursor.getString(_cursorIndexOfUrlId);
        }
        _item_1.setUrlId(_tmpUrlId);
        final String _tmpDisplay;
        if (_cursor.isNull(_cursorIndexOfDisplay)) {
          _tmpDisplay = null;
        } else {
          _tmpDisplay = _cursor.getString(_cursorIndexOfDisplay);
        }
        _item_1.setDisplay(_tmpDisplay);
        _result.add(_item_1);
      }
      return _result;
    } finally {
      _cursor.close();
      _statement.release();
    }
  }

  @Override
  public DataSource.Factory<Integer, VerbDisplay> findAllVerbsAsc(final List<Long> uidList) {
    StringBuilder _stringBuilder = StringUtil.newStringBuilder();
    _stringBuilder.append("SELECT VerbEntity.verbUid, VerbEntity.urlId, XLangMapEntry.valueLangMap AS display ");
    _stringBuilder.append("\n");
    _stringBuilder.append("         FROM VerbEntity LEFT JOIN XLangMapEntry on XLangMapEntry.verbLangMapUid = VerbEntity.verbUid WHERE ");
    _stringBuilder.append("\n");
    _stringBuilder.append("         VerbEntity.verbUid NOT IN (");
    final int _inputSize = uidList.size();
    StringUtil.appendPlaceholders(_stringBuilder, _inputSize);
    _stringBuilder.append(") ORDER BY display ASC");
    final String _sql = _stringBuilder.toString();
    final int _argCount = 0 + _inputSize;
    final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, _argCount);
    int _argIndex = 1;
    for (long _item : uidList) {
      _statement.bindLong(_argIndex, _item);
      _argIndex ++;
    }
    return new DataSource.Factory<Integer, VerbDisplay>() {
      @Override
      public LimitOffsetDataSource<VerbDisplay> create() {
        return new LimitOffsetDataSource<VerbDisplay>(__db, _statement, false, true , "VerbEntity", "XLangMapEntry") {
          @Override
          protected List<VerbDisplay> convertRows(Cursor cursor) {
            final int _cursorIndexOfVerbUid = 0;
            final int _cursorIndexOfUrlId = 1;
            final int _cursorIndexOfDisplay = 2;
            final List<VerbDisplay> _res = new ArrayList<VerbDisplay>(cursor.getCount());
            while(cursor.moveToNext()) {
              final VerbDisplay _item_1;
              _item_1 = new VerbDisplay();
              final long _tmpVerbUid;
              _tmpVerbUid = cursor.getLong(_cursorIndexOfVerbUid);
              _item_1.setVerbUid(_tmpVerbUid);
              final String _tmpUrlId;
              if (cursor.isNull(_cursorIndexOfUrlId)) {
                _tmpUrlId = null;
              } else {
                _tmpUrlId = cursor.getString(_cursorIndexOfUrlId);
              }
              _item_1.setUrlId(_tmpUrlId);
              final String _tmpDisplay;
              if (cursor.isNull(_cursorIndexOfDisplay)) {
                _tmpDisplay = null;
              } else {
                _tmpDisplay = cursor.getString(_cursorIndexOfDisplay);
              }
              _item_1.setDisplay(_tmpDisplay);
              _res.add(_item_1);
            }
            return _res;
          }
        };
      }
    };
  }

  @Override
  public DataSource.Factory<Integer, VerbDisplay> findAllVerbsDesc(final List<Long> uidList) {
    StringBuilder _stringBuilder = StringUtil.newStringBuilder();
    _stringBuilder.append("SELECT VerbEntity.verbUid, VerbEntity.urlId, XLangMapEntry.valueLangMap AS display ");
    _stringBuilder.append("\n");
    _stringBuilder.append("         FROM VerbEntity LEFT JOIN XLangMapEntry on XLangMapEntry.verbLangMapUid = VerbEntity.verbUid WHERE ");
    _stringBuilder.append("\n");
    _stringBuilder.append("        VerbEntity.verbUid NOT IN (");
    final int _inputSize = uidList.size();
    StringUtil.appendPlaceholders(_stringBuilder, _inputSize);
    _stringBuilder.append(") ORDER BY display DESC");
    final String _sql = _stringBuilder.toString();
    final int _argCount = 0 + _inputSize;
    final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, _argCount);
    int _argIndex = 1;
    for (long _item : uidList) {
      _statement.bindLong(_argIndex, _item);
      _argIndex ++;
    }
    return new DataSource.Factory<Integer, VerbDisplay>() {
      @Override
      public LimitOffsetDataSource<VerbDisplay> create() {
        return new LimitOffsetDataSource<VerbDisplay>(__db, _statement, false, true , "VerbEntity", "XLangMapEntry") {
          @Override
          protected List<VerbDisplay> convertRows(Cursor cursor) {
            final int _cursorIndexOfVerbUid = 0;
            final int _cursorIndexOfUrlId = 1;
            final int _cursorIndexOfDisplay = 2;
            final List<VerbDisplay> _res = new ArrayList<VerbDisplay>(cursor.getCount());
            while(cursor.moveToNext()) {
              final VerbDisplay _item_1;
              _item_1 = new VerbDisplay();
              final long _tmpVerbUid;
              _tmpVerbUid = cursor.getLong(_cursorIndexOfVerbUid);
              _item_1.setVerbUid(_tmpVerbUid);
              final String _tmpUrlId;
              if (cursor.isNull(_cursorIndexOfUrlId)) {
                _tmpUrlId = null;
              } else {
                _tmpUrlId = cursor.getString(_cursorIndexOfUrlId);
              }
              _item_1.setUrlId(_tmpUrlId);
              final String _tmpDisplay;
              if (cursor.isNull(_cursorIndexOfDisplay)) {
                _tmpDisplay = null;
              } else {
                _tmpDisplay = cursor.getString(_cursorIndexOfDisplay);
              }
              _item_1.setDisplay(_tmpDisplay);
              _res.add(_item_1);
            }
            return _res;
          }
        };
      }
    };
  }

  public static List<Class<?>> getRequiredConverters() {
    return Collections.emptyList();
  }
}
