/**
  * Calculate the new position of an element
  *
  * Warning this function needs the cdp (current data provider).
  * Warning this function needs the pdp (parent data provider).
  *
  * Based on backbone87 PR - "creating items in parent modes generates sorting value of 0"
  *
  * @param InterfaceGeneralData $objCDP - Current data provider
  * @param InterfaceGeneralData $objPDP - Parent data provider
  * @param InterfaceGeneralModel $objDBModel - Model of element which should moved
  * @param mixed $mixAfter - Target element
  * @param string $strMode - Mode like cut | create and so on
  * @param integer $intInsertMode - Insert Mode => 1 After | 2 Into
  * @param mixed $mixParentID - Parent ID of table or element
  *
  * @return void
  */
 protected function getNewPosition($objCDP, $objPDP, $objDBModel, $mixAfter, $mixInto, $strMode, $mixParentID = null, $intInsertMode = null, $blnWithoutReorder = false)
 {
     // Check if we have a sorting field, if not skip here.
     if (!$objCDP->fieldExists('sorting')) {
         return;
     }
     // Load default DataProvider.
     if (is_null($objCDP)) {
         $objCDP = $this->getDC()->getDataProvider();
     }
     if ($mixAfter === DCGE::INSERT_AFTER_START) {
         $mixAfter = 0;
     }
     // Search for the highest sorting. Default - Add to end off all.
     // ToDo: We have to check the child <=> parent condition . To get all sortings for one level.
     // If we get a after 0, add to top.
     if ($mixAfter === 0) {
         // Build filter for conditions
         $arrFilter = array();
         if (in_array($this->getDC()->arrDCA['list']['sorting']['mode'], array(4, 5, 6))) {
             $arrConditions = $this->objDC->getRootConditions($objCDP->getEmptyModel()->getProviderName());
             if ($arrConditions) {
                 foreach ($arrConditions as $arrCondition) {
                     if (key_exists('remote', $arrCondition)) {
                         $arrFilter[] = array('value' => Input::getInstance()->get($arrCondition['remote']), 'property' => $arrCondition['property'], 'operation' => $arrCondition['operation']);
                     } else {
                         if (key_exists('remote_value', $arrCondition)) {
                             $arrFilter[] = array('value' => Input::getInstance()->get($arrCondition['remote_value']), 'property' => $arrCondition['property'], 'operation' => $arrCondition['operation']);
                         } else {
                             $arrFilter[] = array('value' => $arrCondition['value'], 'property' => $arrCondition['property'], 'operation' => $arrCondition['operation']);
                         }
                     }
                 }
             }
         }
         // Build config
         $objConfig = $objCDP->getEmptyConfig();
         $objConfig->setFields(array('sorting'));
         $objConfig->setSorting(array('sorting' => DCGE::MODEL_SORTING_ASC));
         $objConfig->setAmount(1);
         $objConfig->setFilter($arrFilter);
         $objCollection = $objCDP->fetchAll($objConfig);
         if ($objCollection->length()) {
             $intLowestSorting = $objCollection->get(0)->getProperty('sorting');
             $intNextSorting = round($intLowestSorting / 2);
         } else {
             $intNextSorting = 256;
         }
         // Check if we have a valide sorting.
         if (($intLowestSorting < 2 || $intNextSorting <= 2) && !$blnWithoutReorder) {
             // ToDo: Add child <=> parent config.
             $objConfig = $objCDP->getEmptyConfig();
             $objConfig->setFilter($arrFilter);
             $this->reorderSorting($objConfig);
             $this->getNewPosition($objCDP, $objPDP, $objDBModel, $mixAfter, $mixInto, $strMode, $mixParentID, $intInsertMode, true);
             return;
         } else {
             if ($intNextSorting <= 2) {
                 $intNextSorting = 256;
             }
         }
         $objDBModel->setProperty('sorting', $intNextSorting);
     } else {
         if (!empty($mixAfter)) {
             // Init some vars.
             $intAfterSorting = 0;
             $intNextSorting = 0;
             // Get "after" sorting value value.
             $objAfterConfig = $objCDP->getEmptyConfig();
             $objAfterConfig->setAmount(1);
             $objAfterConfig->setFilter(array(array('value' => $mixAfter, 'property' => 'id', 'operation' => '=')));
             $objAfterCollection = $objCDP->fetchAll($objAfterConfig);
             if ($objAfterCollection->length()) {
                 $intAfterSorting = $objAfterCollection->get(0)->getProperty('sorting');
             }
             // Get "next" sorting value value.
             $objNextConfig = $objCDP->getEmptyConfig();
             $objNextConfig->setFields(array('sorting'));
             $objNextConfig->setAmount(1);
             $objNextConfig->setSorting(array('sorting' => DCGE::MODEL_SORTING_ASC));
             $arrFilterSettings = array(array('value' => $intAfterSorting, 'property' => 'sorting', 'operation' => '>'));
             $arrFilterChildCondition = array();
             // If we have mode 4, 5, 6 build the child <=> parent condition.
             if (in_array($this->getDC()->arrDCA['list']['sorting']['mode'], array(4, 5, 6))) {
                 $arrChildCondition = $this->objDC->getParentChildCondition($objAfterCollection->get(0), $objCDP->getEmptyModel()->getProviderName());
                 $arrChildCondition = $arrChildCondition['setOn'];
                 if ($arrChildCondition) {
                     foreach ($arrChildCondition as $arrOperation) {
                         if (array_key_exists('to_field', $arrOperation)) {
                             $arrFilterChildCondition[] = array('value' => $objAfterCollection->get(0)->getProperty($arrOperation['to_field']), 'property' => $arrOperation['to_field'], 'operation' => '=');
                         } else {
                             $arrFilterChildCondition[] = array('value' => $arrOperation['property'], 'property' => $arrOperation['to_field'], 'operation' => '=');
                         }
                     }
                 }
             }
             $objNextConfig->setFilter(array_merge($arrFilterSettings, $arrFilterChildCondition));
             $objNextCollection = $objCDP->fetchAll($objNextConfig);
             if ($objNextCollection->length()) {
                 $intNextSorting = $objNextCollection->get(0)->getProperty('sorting');
             } else {
                 $intNextSorting = $intAfterSorting + 2 * 256;
             }
             // Check if we have a valide sorting.
             if (($intAfterSorting < 2 || $intNextSorting < 2 || round(($intNextSorting - $intAfterSorting) / 2) <= 2) && !$blnWithoutReorder) {
                 // ToDo: Add child <=> parent config.
                 $objConfig = $objCDP->getEmptyConfig();
                 $objConfig->setFilter($arrFilterChildCondition);
                 $this->reorderSorting($objConfig);
                 $this->getNewPosition($objCDP, $objPDP, $objDBModel, $mixAfter, $mixInto, $strMode, $mixParentID, $intInsertMode, true);
                 return;
             } else {
                 if ($intNextSorting <= 2) {
                     $intNextSorting = 256;
                 }
             }
             // Get sorting between these two values.
             $intNewSorting = $intAfterSorting + round(($intNextSorting - $intAfterSorting) / 2);
             // Save in model.
             $objDBModel->setProperty('sorting', $intNewSorting);
         } else {
             $objConfig = $objCDP->getEmptyConfig();
             $objConfig->setFields(array('sorting'));
             $objConfig->setSorting(array('sorting' => DCGE::MODEL_SORTING_DESC));
             $objConfig->setAmount(1);
             $objCollection = $objCDP->fetchAll($objConfig);
             $intHighestSorting = 0;
             if ($objCollection->length()) {
                 $intHighestSorting = $objCollection->get(0)->getProperty('sorting') + 256;
             }
             $objDBModel->setProperty('sorting', $intHighestSorting);
         }
     }
 }