/**
   * ახალი სატელეფონო კომპანიის და მისი ინდექსების დამატების ფუნქციონალი.
   *
   * @param dsRequest ამ პარამეტრში მოდის თუ რა ინფორმაცია უნდა შეინახოს სატელეფონო კომპანიის
   *     შესახებ
   * @return BillingComp ფუნქცია აბრუნებს ჰიბერნეიტის კლასს რომელიც უკვე შენახულია მონაცმთა ბაზაში.
   *     ეს კლასი ბრუნდება კლიენტის მხარეს რათა კლიენტმა დაინახოს მის მიერ ახალ დამატებული
   *     სატელეფონო კომპანია
   * @throws Exception შეცდომის დამუშავება.
   */
  @SuppressWarnings("rawtypes")
  public BillingCompany addBillingComp(DSRequest dsRequest) throws Exception {
    EntityManager oracleManager = null;
    Object transaction = null;
    try {
      String log = "Method:BillingCompsDMI.addBillingComp.";

      String loggedUserName = dsRequest.getFieldValue("loggedUserName").toString();

      // sysdate
      Timestamp rec_date = new Timestamp(System.currentTimeMillis());

      BillingCompany billingComp = new BillingCompany();
      billingComp.setLoggedUserName(loggedUserName);

      Object obilling_company_name = dsRequest.getFieldValue("billing_company_name");
      String billing_company_name =
          (obilling_company_name == null ? null : obilling_company_name.toString());
      billingComp.setBilling_company_name(billing_company_name);

      Object oour_percent = dsRequest.getFieldValue("our_percent");
      Double our_percent = (oour_percent == null ? 1L : new Double(oour_percent.toString()));
      billingComp.setOur_percent(our_percent);

      Object ocall_price = dsRequest.getFieldValue("call_price");
      Double call_price = (ocall_price == null ? 1L : new Double(ocall_price.toString()));
      billingComp.setCall_price(call_price);

      Object ohas_calculation = dsRequest.getFieldValue("has_calculation");
      Long has_calculation =
          (ohas_calculation == null ? -1L : new Long(ohas_calculation.toString()));
      billingComp.setHas_calculation(has_calculation);

      Long operator_src = Long.parseLong(dsRequest.getFieldValue("operator_src").toString());
      Long mobile_company = Long.parseLong(dsRequest.getFieldValue("mobile_company").toString());

      Object mobile_company_name_o = dsRequest.getFieldValue("mobile_company_name");
      String mobile_company_name =
          (mobile_company_name_o == null ? null : mobile_company_name_o.toString());

      billingComp.setOperator_src(operator_src);
      billingComp.setMobile_company(mobile_company);
      billingComp.setMobile_company_name(mobile_company_name);

      oracleManager = EMF.getEntityManager();
      transaction = EMF.getTransaction(oracleManager);

      RCNGenerator.getInstance()
          .initRcn(oracleManager, rec_date, loggedUserName, "Adding BillingComp.");

      oracleManager.persist(billingComp);
      oracleManager.flush();

      Object oMap = dsRequest.getFieldValue("billingCompIdexes");
      if (oMap != null) {
        LinkedMap indexed = (LinkedMap) oMap;
        if (!indexed.isEmpty()) {
          Set keys1 = indexed.keySet();
          checkBillingCompIndexes(null, operator_src, indexed);
          for (Object okey1 : keys1) {
            String str_bill_index_start = okey1.toString();
            LinkedMap value1 = (LinkedMap) indexed.get(str_bill_index_start);
            String str_bill_index_end = value1.get("str_bill_index_end").toString();
            String str_applied_wholly = value1.get("str_applied_wholly").toString();
            String str_calcul_type = value1.get("str_calcul_type").toString();

            BillingCompanyInd item = new BillingCompanyInd();
            item.setApplied_wholly(new Long(str_applied_wholly));
            item.setBill_index_end(new Long(str_bill_index_end));
            item.setBill_index_start(new Long(str_bill_index_start));
            item.setCalcul_type(new Long(str_calcul_type));
            item.setBilling_company_id(billingComp.getbilling_company_id());
            oracleManager.persist(item);
          }
        }
      }

      billingComp = oracleManager.find(BillingCompany.class, billingComp.getbilling_company_id());
      billingComp.setLoggedUserName(loggedUserName);
      if (has_calculation.equals(1L)) {
        billingComp.setHas_calculation_descr("დიახ");
      } else if (has_calculation.equals(0L)) {
        billingComp.setHas_calculation_descr("არა");
      } else {
        billingComp.setHas_calculation_descr("ყველა");
      }

      EMF.commitTransaction(transaction);
      log += ". Inserting Finished SuccessFully. ";
      logger.info(log);
      return billingComp;
    } catch (Exception e) {
      EMF.rollbackTransaction(transaction);
      if (e instanceof CallCenterException) {
        throw (CallCenterException) e;
      }
      logger.error("Error While Insert BillingComp Into Database : ", e);
      throw new CallCenterException("შეცდომა მონაცემების შენახვისას : " + e.toString());
    } finally {
      if (oracleManager != null) {
        EMF.returnEntityManager(oracleManager);
      }
    }
  }
  /** Tests that on snapshots, states and offsets to commit to Kafka are correct */
  @Test
  @SuppressWarnings("unchecked")
  public void testSnapshotState() throws Exception {

    // --------------------------------------------------------------------
    //   prepare fake states
    // --------------------------------------------------------------------

    final HashMap<KafkaTopicPartition, Long> state1 = new HashMap<>();
    state1.put(new KafkaTopicPartition("abc", 13), 16768L);
    state1.put(new KafkaTopicPartition("def", 7), 987654321L);

    final HashMap<KafkaTopicPartition, Long> state2 = new HashMap<>();
    state2.put(new KafkaTopicPartition("abc", 13), 16770L);
    state2.put(new KafkaTopicPartition("def", 7), 987654329L);

    final HashMap<KafkaTopicPartition, Long> state3 = new HashMap<>();
    state3.put(new KafkaTopicPartition("abc", 13), 16780L);
    state3.put(new KafkaTopicPartition("def", 7), 987654377L);

    // --------------------------------------------------------------------

    final AbstractFetcher<String, ?> fetcher = mock(AbstractFetcher.class);
    when(fetcher.snapshotCurrentState()).thenReturn(state1, state2, state3);

    final LinkedMap pendingOffsetsToCommit = new LinkedMap();

    FlinkKafkaConsumerBase<String> consumer = getConsumer(fetcher, pendingOffsetsToCommit, true);
    assertEquals(0, pendingOffsetsToCommit.size());

    OperatorStateStore backend = mock(OperatorStateStore.class);

    TestingListState<Serializable> init = new TestingListState<>();
    TestingListState<Serializable> listState1 = new TestingListState<>();
    TestingListState<Serializable> listState2 = new TestingListState<>();
    TestingListState<Serializable> listState3 = new TestingListState<>();

    when(backend.getSerializableListState(Matchers.any(String.class)))
        .thenReturn(init, listState1, listState2, listState3);

    consumer.initializeState(backend);

    // checkpoint 1
    consumer.prepareSnapshot(138L, 138L);

    HashMap<KafkaTopicPartition, Long> snapshot1 = new HashMap<>();

    for (Serializable serializable : listState1.get()) {
      Tuple2<KafkaTopicPartition, Long> kafkaTopicPartitionLongTuple2 =
          (Tuple2<KafkaTopicPartition, Long>) serializable;
      snapshot1.put(kafkaTopicPartitionLongTuple2.f0, kafkaTopicPartitionLongTuple2.f1);
    }

    assertEquals(state1, snapshot1);
    assertEquals(1, pendingOffsetsToCommit.size());
    assertEquals(state1, pendingOffsetsToCommit.get(138L));

    // checkpoint 2
    consumer.prepareSnapshot(140L, 140L);

    HashMap<KafkaTopicPartition, Long> snapshot2 = new HashMap<>();

    for (Serializable serializable : listState2.get()) {
      Tuple2<KafkaTopicPartition, Long> kafkaTopicPartitionLongTuple2 =
          (Tuple2<KafkaTopicPartition, Long>) serializable;
      snapshot2.put(kafkaTopicPartitionLongTuple2.f0, kafkaTopicPartitionLongTuple2.f1);
    }

    assertEquals(state2, snapshot2);
    assertEquals(2, pendingOffsetsToCommit.size());
    assertEquals(state2, pendingOffsetsToCommit.get(140L));

    // ack checkpoint 1
    consumer.notifyCheckpointComplete(138L);
    assertEquals(1, pendingOffsetsToCommit.size());
    assertTrue(pendingOffsetsToCommit.containsKey(140L));

    // checkpoint 3
    consumer.prepareSnapshot(141L, 141L);

    HashMap<KafkaTopicPartition, Long> snapshot3 = new HashMap<>();

    for (Serializable serializable : listState3.get()) {
      Tuple2<KafkaTopicPartition, Long> kafkaTopicPartitionLongTuple2 =
          (Tuple2<KafkaTopicPartition, Long>) serializable;
      snapshot3.put(kafkaTopicPartitionLongTuple2.f0, kafkaTopicPartitionLongTuple2.f1);
    }

    assertEquals(state3, snapshot3);
    assertEquals(2, pendingOffsetsToCommit.size());
    assertEquals(state3, pendingOffsetsToCommit.get(141L));

    // ack checkpoint 3, subsumes number 2
    consumer.notifyCheckpointComplete(141L);
    assertEquals(0, pendingOffsetsToCommit.size());

    consumer.notifyCheckpointComplete(666); // invalid checkpoint
    assertEquals(0, pendingOffsetsToCommit.size());

    OperatorStateStore operatorStateStore = mock(OperatorStateStore.class);
    TestingListState<Tuple2<KafkaTopicPartition, Long>> listState = new TestingListState<>();
    when(operatorStateStore.getOperatorState(Matchers.any(ListStateDescriptor.class)))
        .thenReturn(listState);

    // create 500 snapshots
    for (int i = 100; i < 600; i++) {
      consumer.prepareSnapshot(i, i);
      listState.clear();
    }
    assertEquals(FlinkKafkaConsumerBase.MAX_NUM_PENDING_CHECKPOINTS, pendingOffsetsToCommit.size());

    // commit only the second last
    consumer.notifyCheckpointComplete(598);
    assertEquals(1, pendingOffsetsToCommit.size());

    // access invalid checkpoint
    consumer.notifyCheckpointComplete(590);

    // and the last
    consumer.notifyCheckpointComplete(599);
    assertEquals(0, pendingOffsetsToCommit.size());
  }
  @SuppressWarnings("rawtypes")
  public void checkBillingCompIndexes(Long billing_company_id, Long operator_src, LinkedMap indexes)
      throws Exception {
    EntityManager oracleManager = null;
    try {
      String log = "Method:BillingCompsDMI.checkBillingCompIndexes.";
      oracleManager = EMF.getEntityManager();
      if (!indexes.isEmpty()) {
        Set keys1 = indexes.keySet();

        if (billing_company_id == null) {
          billing_company_id = -111111111L;
        }

        for (Object okey1 : keys1) {
          String str_st_ind = okey1.toString();
          LinkedMap value1 = (LinkedMap) indexes.get(str_st_ind);
          String str_bill_index_end = value1.get("str_bill_index_end").toString();
          Long st_ind = new Long(str_st_ind);
          Long end_ind = new Long(str_bill_index_end);

          Long count = 0L;
          if (billing_company_id.equals(-111111111L)) {
            count =
                new Long(
                    oracleManager
                        .createNativeQuery(QueryConstants.Q_GET_BILLING_COMP_IND)
                        .setParameter(1, st_ind)
                        .setParameter(2, operator_src)
                        .getSingleResult()
                        .toString());
          } else {
            count =
                new Long(
                    oracleManager
                        .createNativeQuery(QueryConstants.Q_GET_BILLING_COMP_IND_BY_ID)
                        .setParameter(1, st_ind)
                        .setParameter(2, billing_company_id)
                        .setParameter(3, operator_src)
                        .getSingleResult()
                        .toString());
          }
          if (count.longValue() > 0) {
            throw new CallCenterException("მსგავსი ინდექსი უკვე რეგისტრირებულია : " + st_ind);
          }
          if (billing_company_id.equals(-111111111L)) {
            count =
                new Long(
                    oracleManager
                        .createNativeQuery(QueryConstants.Q_GET_BILLING_COMP_IND)
                        .setParameter(1, end_ind)
                        .setParameter(2, operator_src)
                        .getSingleResult()
                        .toString());
          } else {
            count =
                new Long(
                    oracleManager
                        .createNativeQuery(QueryConstants.Q_GET_BILLING_COMP_IND_BY_ID)
                        .setParameter(1, end_ind)
                        .setParameter(2, billing_company_id)
                        .setParameter(3, operator_src)
                        .getSingleResult()
                        .toString());
          }
          if (count.longValue() > 0) {
            throw new CallCenterException("მსგავსი ინდექსი უკვე რეგისტრირებულია : " + end_ind);
          }
        }
      }
      log += ". Check Finished SuccessFully. ";
      logger.info(log);
    } catch (Exception e) {
      if (e instanceof CallCenterException) {
        throw (CallCenterException) e;
      }
      logger.error("Error While Checking BillingComp Indexes Into Database : ", e);
      throw new CallCenterException("შეცდომა მონაცემების შემოწმებისას : " + e.toString());
    } finally {
      if (oracleManager != null) {
        EMF.returnEntityManager(oracleManager);
      }
    }
  }