/**
  * Formulář pro zadání preprocessingu pomocí interval enumeration
  * @return Form
  */
 protected function createComponentNewIntervalEnumerationForm()
 {
     $form = new Form();
     $form->setTranslator($this->translator);
     $form->addText('preprocessingName', 'Preprocessing name:')->setRequired(false)->setAttribute('placeholder', $this->translate('Interval bins'))->setAttribute('title', $this->translate('You can left this field blank, it will be filled in automatically.'))->addRule(function (TextInput $textInput) {
         $form = $textInput->getForm(true);
         $formValues = $form->getValues(true);
         $textInputValue = $textInput->value;
         //nalezení aktuálního formátu
         $miner = $this->findMinerWithCheckAccess($formValues['miner']);
         $datasourceColumn = $this->findDatasourceColumn($miner->datasource, $formValues['column']);
         $format = $datasourceColumn->format;
         $textInput->setAttribute('placeholder', $this->prepareIntervalEnumerationPreprocessingName($format, $formValues));
         if ($textInputValue != '') {
             //check preprocessings
             $existingPreprocessings = $format->preprocessings;
             if (!empty($existingPreprocessings)) {
                 foreach ($existingPreprocessings as $existingPreprocessing) {
                     if ($existingPreprocessing->name == $textInput) {
                         return false;
                     }
                 }
             }
         }
         return true;
     }, 'This preprocessing name already exists. Please select a new one...')->addRule(function (TextInput $input) {
         $values = $input->getForm(true)->getValues(true);
         return count($values['valuesBins']) > 0;
     }, 'You have to input at least one bin!');
     $form->addText('attributeName', 'Create attribute with name:')->setRequired('Input attribute name!')->addRule(Form::PATTERN, 'Attribute name can contain only letters, numbers and _ and has start with a letter.', '[a-zA-Z]{1}\\w*')->addRule(function (TextInput $input) {
         //kontrola, jestli již existuje atribtu se zadaným názvem
         $values = $input->getForm(true)->getValues();
         $miner = $this->findMinerWithCheckAccess($values->miner);
         $attributes = $miner->metasource->attributes;
         if (!empty($attributes)) {
             foreach ($attributes as $attribute) {
                 if ($attribute->name == $input->value) {
                     return false;
                 }
             }
         }
         return true;
     }, 'Attribute with this name already exists!');
     $form->addHidden('column');
     $form->addHidden('miner');
     /** @var Container $valuesBins */
     /** @noinspection PhpUndefinedMethodInspection */
     $valuesBins = $form->addDynamic('valuesBins', function (Container $valuesBin) {
         $valuesBin->addText('name', 'Bin name:')->setRequired(true)->setRequired('Input bin name!')->addRule(function (TextInput $input) {
             /** @var Container $container */
             $container = $input->parent;
             $values = $container->getValues(true);
             return count($values['intervals']) > 0;
         }, 'Add at least one interval!')->addRule(function (TextInput $input) {
             //kontrola, jestli má každý BIN jiný název
             $values = $input->getParent()->getParent()->getValues(true);
             $inputValue = $input->getValue();
             $usesCount = 0;
             if (!empty($values)) {
                 foreach ($values as $value) {
                     if ($value['name'] == $inputValue) {
                         $usesCount++;
                     }
                 }
             }
             return $usesCount <= 1;
         }, 'This name is used for other bin!');
         /** @var Container $intervals */
         $intervals = $valuesBin->addDynamic('intervals', function (Container $interval) {
             $interval->addHidden('leftValue');
             $interval->addHidden('leftBound');
             $interval->addHidden('rightValue');
             $interval->addHidden('rightBound');
             $interval->addText('text')->setAttribute('readonly');
             $interval->addSubmit('remove', 'x')->setValidationScope([])->onClick[] = function (SubmitButton $submitButton) {
                 $intervals = $submitButton->getParent()->getParent();
                 $intervals->remove($submitButton->parent, TRUE);
             };
         });
         $addIntervalSubmit = $valuesBin->addSubmit('addInterval', 'Add interval');
         $valuesBin->addSelect('leftBound', null, ['closed' => '[', 'open' => '(']);
         $leftValue = $valuesBin->addText('leftValue')->setDefaultValue('');
         $leftValue->addConditionOn($addIntervalSubmit, Form::SUBMITTED)->setRequired('Input start value!')->addRule(Form::FLOAT, 'You have to input number!');
         $rightValue = $valuesBin->addText('rightValue')->setDefaultValue('');
         $rightValue->addConditionOn($addIntervalSubmit, Form::SUBMITTED)->setRequired('Input end value!')->addRule(Form::FLOAT, 'You have to input number!')->addRule(function (TextInput $input) use($addIntervalSubmit) {
             $values = $input->getParent()->getValues(true);
             if ($values['leftValue'] > $values['rightValue']) {
                 return false;
             }
             if ($values['leftValue'] == $values['rightValue'] && ($values['leftBound'] != Interval::CLOSURE_CLOSED || $values['rightBound'] != Interval::CLOSURE_CLOSED)) {
                 return false;
             }
             return true;
         }, 'Interval end cannot be lower than start value!')->addRule(function (TextInput $input) {
             //kontrola překryvu intervalu
             $parentValues = $input->getParent()->getValues(true);
             $interval = Interval::create($parentValues['leftBound'], $parentValues['leftValue'], $parentValues['rightValue'], $parentValues['rightBound']);
             $valuesBinsValues = $input->getParent()->getParent()->getValues(true);
             if (!empty($valuesBinsValues)) {
                 foreach ($valuesBinsValues as $valuesBin) {
                     if (!empty($valuesBin['intervals'])) {
                         foreach ($valuesBin['intervals'] as $intervalValues) {
                             if ($interval->isInOverlapWithInterval(Interval::create($intervalValues['leftBound'], $intervalValues['leftValue'], $intervalValues['rightValue'], $intervalValues['rightBound']))) {
                                 return false;
                             }
                         }
                     }
                 }
             }
             return true;
         }, 'Interval overlaps with another one!');
         $valuesBin->addSelect('rightBound', null, ['closed' => ']', 'open' => ')']);
         $addIntervalSubmit->setValidationScope([$leftValue, $rightValue])->onClick[] = function (SubmitButton $submitButton) use($intervals) {
             /** @var Container $intervalsForm */
             $intervalsForm = $submitButton->parent;
             $values = $intervalsForm->getValues(true);
             $interval = $intervals->createOne();
             $interval->setValues(['leftBound' => $values['leftBound'], 'rightBound' => $values['rightBound'], 'leftValue' => $values['leftValue'], 'rightValue' => $values['rightValue'], 'text' => StringsHelper::formatIntervalString($values['leftBound'], $values['leftValue'], $values['rightValue'], $values['rightBound'])]);
             $intervalsForm->setValues(['leftValue' => '', 'rightValue' => '']);
         };
         $valuesBin->addSubmit('remove', 'Remove bin')->setAttribute('class', 'removeBin')->setValidationScope([])->onClick[] = function (SubmitButton $submitButton) {
             $submitButton->getParent()->getParent()->remove($submitButton->getParent(), true);
         };
     }, 0);
     $valuesBins->addSubmit('addBin', 'Add bin')->setValidationScope([])->onClick[] = function (SubmitButton $submitButton) {
         $submitButton->getParent()->createOne();
     };
     $form->addSubmit('submitAll', 'Save preprocessing & create attribute')->onClick[] = function (SubmitButton $submitButton) {
         #region vytvoření preprocessingu
         $values = $submitButton->getForm(true)->getValues(true);
         $miner = $this->findMinerWithCheckAccess($values['miner']);
         $this->minersFacade->checkMinerMetasource($miner);
         //vytvoření preprocessingu
         $datasourceColumn = $this->findDatasourceColumn($miner->datasource, $values['column']);
         $format = $datasourceColumn->format;
         $preprocessing = new Preprocessing();
         $preprocessing->name = $values['preprocessingName'] != '' ? $values['preprocessingName'] : $this->prepareIntervalEnumerationPreprocessingName($format, $values);
         $preprocessing->format = $format;
         $preprocessing->user = $this->getCurrentUser();
         $this->preprocessingsFacade->savePreprocessing($preprocessing);
         foreach ($values['valuesBins'] as $valuesBinValues) {
             $valuesBin = new ValuesBin();
             $valuesBin->format = $format;
             $valuesBin->name = $valuesBinValues['name'];
             $this->metaAttributesFacade->saveValuesBin($valuesBin);
             foreach ($valuesBinValues['intervals'] as $intervalValues) {
                 $interval = Interval::create($intervalValues['leftBound'], $intervalValues['leftValue'], $intervalValues['rightValue'], $intervalValues['rightBound']);
                 $interval->format = null;
                 //TODO kontrola, aby se zbytečně nevytvářely stejné atributy
                 $this->metaAttributesFacade->saveInterval($interval);
                 $valuesBin->addToIntervals($interval);
             }
             $this->metaAttributesFacade->saveValuesBin($valuesBin);
             $preprocessing->addToValuesBins($valuesBin);
         }
         $this->preprocessingsFacade->savePreprocessing($preprocessing);
         //vytvoření atributu
         $attribute = new Attribute();
         $attribute->metasource = $miner->metasource;
         $attribute->datasourceColumn = $datasourceColumn;
         $attribute->name = $values['attributeName'];
         $attribute->type = $attribute->datasourceColumn->type;
         $attribute->preprocessing = $preprocessing;
         $this->minersFacade->prepareAttribute($miner, $attribute);
         $this->metasourcesFacade->saveAttribute($attribute);
         $this->minersFacade->checkMinerState($miner, $this->getCurrentUser());
         $this->redirect('reloadUI');
         #endregion vytvoření preprocessingu
     };
     $presenter = $this;
     $form->addSubmit('storno', 'storno')->setValidationScope([])->onClick[] = function (SubmitButton $submitButton) use($presenter) {
         $values = $submitButton->getForm()->getValues();
         $presenter->redirect('addAttribute', array('column' => $values->column, 'miner' => $values->miner));
     };
     return $form;
 }
 /**
  * Funkce pro aktualizaci formátu na základě hodnot z daného DatasourceColumn
  * TODO implementovat...
  * @param Format $format
  * @param DatasourceColumn $datasourceColumn
  * @param DbColumnValuesStatistic $columnValuesStatistic
  */
 public function updateFormatFromDatasourceColumn(Format $format, DatasourceColumn $datasourceColumn, DbColumnValuesStatistic $columnValuesStatistic)
 {
     if ($format->dataType == Format::DATATYPE_INTERVAL) {
         $newInterval = Interval::create(Interval::CLOSURE_CLOSED, $columnValuesStatistic->minValue, $columnValuesStatistic->maxValue, Interval::CLOSURE_CLOSED);
         $newInterval->format = $format;
         $intervals = $format->intervals;
         if (!empty($intervals)) {
             if (count($intervals) == 1) {
                 $originalInterval = $intervals[0];
                 if ($originalInterval->leftMargin > $newInterval->leftMargin || $originalInterval->leftMargin == $newInterval->leftMargin && ($originalInterval->leftClosure = Interval::CLOSURE_OPEN)) {
                     $originalInterval->leftMargin = $newInterval->leftMargin;
                     $originalInterval->leftClosure = $newInterval->leftClosure;
                 }
                 if ($originalInterval->rightMargin < $newInterval->rightMargin || $originalInterval->rightMargin == $newInterval->rightMargin && ($originalInterval->rightClosure = Interval::CLOSURE_OPEN)) {
                     $originalInterval->rightMargin = $newInterval->rightMargin;
                     $originalInterval->rightClosure = $newInterval->rightClosure;
                 }
                 $this->saveInterval($originalInterval);
             } else {
                 //FIXME možné rozšíření množiny intervalů
             }
         } else {
             $this->saveInterval($newInterval);
         }
     } else {
         $existingValues = [];
         $values = $format->values;
         if (!empty($values)) {
             foreach ($values as $value) {
                 $existingValues[] = $value->value;
             }
         }
         if (!empty($columnValuesStatistic->valuesArr)) {
             foreach ($columnValuesStatistic->valuesArr as $value => $count) {
                 if (!in_array($value, $existingValues)) {
                     $valueObject = new Value();
                     $valueObject->format = $format;
                     $valueObject->value = $value;
                     $this->saveValue($valueObject);
                 }
             }
         }
     }
 }