/**
  * Finds or creates values for this type.
  *
  * @param array $values
  *
  * @return ArrayList
  */
 public function convertArrayToValues(array $values)
 {
     $set = ArrayList::create();
     foreach ($values as $value) {
         $val = $this->Values()->find('Value', $value);
         if (!$val) {
             //TODO: ignore case, if possible
             $val = ProductAttributeValue::create();
             $val->Value = $value;
             $val->TypeID = $this->ID;
             $val->write();
         }
         $set->push($val);
     }
     return $set;
 }
 protected function createVariations()
 {
     $this->alterationMessage("================================================ CREATING VARIATIONS ================================================", "show");
     foreach ($this->data as $data) {
         $types = array();
         $values = array();
         $product = $data["Product"];
         $arrayForCreation = array();
         $variationFilter = array();
         $this->alterationMessage("<h1>Working out variations for " . $product->Title . "</h1>");
         //create attribute types for one product
         $this->alterationMessage("....Creating attribute types");
         foreach ($this->Config()->get("attribute_type_field_names") as $fieldKey => $fieldName) {
             $startMessage = "........Checking field {$fieldName}";
             $attributeTypeName = trim($data["Product"]->Title) . "_" . $fieldName;
             $filterArray = array("Name" => $attributeTypeName);
             $type = ProductAttributeType::get()->filter($filterArray)->first();
             if (!$type) {
                 $this->alterationMessage($startMessage . " ... creating new attribute type: " . $attributeTypeName, "created");
                 $type = new ProductAttributeType($filterArray);
                 $type->Label = $attributeTypeName;
                 $type->Sort = $fieldKey;
             } else {
                 $this->alterationMessage($startMessage . " ... \tfound existing attribute type: " . $attributeTypeName);
             }
             $this->addMoreAttributeType($type, $fieldName, $product);
             $type->write();
             $types[$fieldName] = $type;
             $product->VariationAttributes()->add($type);
         }
         //go through each variation to make the values
         $this->alterationMessage("....Creating attribute values");
         foreach ($data["VariationRows"] as $key => $row) {
             //go through each value
             foreach ($this->Config()->get("attribute_type_field_names") as $fieldName) {
                 if (!isset($row["Data"][$fieldName])) {
                     $this->alterationMessage("ERROR; {$fieldName} not set at all....", "deleted");
                     continue;
                 } elseif (!trim($row["Data"][$fieldName])) {
                     $this->alterationMessage("skipping {$fieldName} as there are no entries...");
                     continue;
                 }
                 $startMessage = "........Checking field {$fieldName}";
                 //create attribute value
                 $attributeValueName = $row["Data"][$fieldName];
                 $filterArray = array("Code" => $attributeValueName, "TypeID" => $types[$fieldName]->ID);
                 $value = ProductAttributeValue::get()->filter($filterArray)->first();
                 if (!$value) {
                     $this->alterationMessage($startMessage . "............creating new attribute value:  <strong>" . $attributeValueName . "</strong> for " . $types[$fieldName]->Name, "created");
                     $value = ProductAttributeValue::create($filterArray);
                     $value->Code = $attributeValueName;
                     $value->Value = $attributeValueName;
                 } else {
                     $this->alterationMessage($startMessage . "............found existing attribute value: <strong>" . $attributeValueName . "</strong> for " . $types[$fieldName]->Name);
                 }
                 $this->addMoreAttributeType($value, $types[$fieldName], $product);
                 $value->write();
                 $values[$fieldName] = $value;
                 //add at arrays for creation...
                 if (!isset($arrayForCreation[$types[$fieldName]->ID])) {
                     $arrayForCreation[$types[$fieldName]->ID] = array();
                 }
                 $arrayForCreation[$types[$fieldName]->ID][] = $value->ID;
                 if (!isset($variationFilters[$key])) {
                     $variationFilters[$key] = array();
                 }
                 $variationFilters[$key][$types[$fieldName]->ID] = $value->ID;
             }
         }
         //remove attribute types without values... (i.e. product only has size of colour)
         foreach ($product->VariationAttributes() as $productTypeToBeDeleted) {
             if ($productTypeToBeDeleted->Values()->count() == 0) {
                 $this->alterationMessage("....deleting attribute type with no values: " . $productTypeToBeDeleted->Title);
                 $product->VariationAttributes()->remove($productTypeToBeDeleted);
             }
         }
         $this->alterationMessage("....Creating Variations ///");
         //$this->alterationMessage("....Creating Variations From: ".print_r(array_walk($arrayForCreation, array($this, 'implodeWalk'))));
         //generate variations
         $variationAttributeValuesPerVariation = array();
         foreach ($arrayForCreation as $typeID => $variationEntry) {
             foreach ($variationEntry as $positionOfVariation => $attributeValueID) {
                 $variationAttributeValuesPerVariation[$positionOfVariation][$typeID] = $attributeValueID;
             }
         }
         foreach ($variationAttributeValuesPerVariation as $variationAttributes) {
             $variation = $product->getVariationByAttributes($variationAttributes);
             if ($variation instanceof ProductVariation) {
                 $this->alterationMessage(".... Variation " . $variation->FullName . " Already Exists ///");
             } else {
                 //2. if not, create variation with attributes
                 $className = $product->getClassNameOfVariations();
                 $newVariation = new $className(array('ProductID' => $product->ID, 'Price' => $product->Price));
                 $newVariation->setSaveParentProduct(false);
                 $newVariation->write();
                 $newVariation->AttributeValues()->addMany($variationAttributes);
                 $this->alterationMessage(".... Variation " . $newVariation->FullName . " created ///", "created");
             }
         }
         //find variations and add to VariationsRows
         foreach ($data["VariationRows"] as $key => $row) {
             $variation = $product->getVariationByAttributes($variationFilters[$key]);
             if ($variation instanceof ProductVariation) {
                 $this->alterationMessage("........Created variation, " . $variation->getTitle());
                 $this->data[$product->ID]["VariationRows"][$key]["Variation"] = $variation;
             } else {
                 $this->alterationMessage("........Could not find variation", "deleted");
             }
         }
     }
     $this->alterationMessage("================================================", "show");
 }