package org.beigesoft.orm.service;

/*
 * Beigesoft ™
 *
 * Licensed under the Apache License, Version 2.0
 *
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 */

import java.lang.reflect.Field;

import org.beigesoft.exception.ExceptionWithCode;
import org.beigesoft.orm.model.IRecordSet;
import org.beigesoft.orm.model.ColumnsValues;

/**
 * <p>ORM service with RDBMS specific INSERT implementation.
 * Insert must fill ID for entities that have autogenerated ID.
 * </p>
 *
 * @param <RS> platform dependent record set type
 * @author Yury Demidenko
 */
public class SrvOrmSqlite<RS> extends ASrvOrm<RS> {

  /**
   * <p>Insert entity into DB.
   * For autogenerated ID fill it in the entity</p>
   * @param <T> entity type
   * @param pEntity entity
   * @throws Exception - an exception
   **/
  @Override
  public final <T> void insertEntity(
    final T pEntity) throws Exception {
    ColumnsValues columnsValues = evalColumnsValuesAndFillNewVersion(pEntity);
    long result = getSrvDatabase().executeInsert(pEntity.getClass()
      .getSimpleName().toUpperCase(), columnsValues);
    if (result != 1) {
      String query = getHlpInsertUpdate().evalSqlInsert(
        pEntity.getClass().getSimpleName().toUpperCase(),
          columnsValues);
      throw new ExceptionWithCode(ISrvDatabase.ERROR_INSERT_UPDATE,
        "It should be 1 row inserted but it is "
          + result + ", query:\n" + query + ";\n");
    }
    String idName = columnsValues.getIdName();
    if (idName != null) { // if non-complex PK
      Field fieldId = getUtlReflection()
                .retrieveField(pEntity.getClass(),
                idName);
      fieldId.setAccessible(true);
      Object idValue = fieldId.get(pEntity);
      if (idValue == null) {
        //It must be an autogenerated Integer or Long ID
        IRecordSet<RS> recordSet = null;
        try {
          String insertedIdName = "INSERTEDID";
          recordSet = getSrvDatabase().retrieveRecords(
            "select last_insert_rowid() as " + insertedIdName + ";");
          recordSet.moveToFirst();
          if (fieldId.getType() == Long.class) {
            fieldId.set(pEntity, getSrvRecordRetriever()
              .getLong(recordSet.getRecordSet(), insertedIdName));
          } else if (fieldId.getType() == Integer.class) {
            fieldId.set(pEntity, getSrvRecordRetriever()
              .getInteger(recordSet.getRecordSet(), insertedIdName));
          } else {
            String msg = "There is no rule to fill ID "
              + fieldId.getName().toUpperCase()
                + " of " + fieldId.getType() + " in "
                  + pEntity;
            throw new ExceptionWithCode(ExceptionWithCode.NOT_YET_IMPLEMENTED,
              msg);
          }
        } finally {
          if (recordSet != null) {
            recordSet.close();
          }
        }
      }
    }
  }
}
