<?php

namespace App\Http\Controllers\Parser;

use App\City;
use App\ClassHousing;
use App\CourseOfConstruction;
use App\Developer;
use App\District;
use App\Heating;
use App\Helpers\ImageSize;
use App\Helpers\ResidentialComplexMapping;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Traits\ImageUploadTrait;
use App\Http\Controllers\Traits\Transliteration;
use App\Planning;
use App\Price;
use App\Quarterly;
use App\ResidentialComplex;
use App\ResidentialComplexCharacter;
use App\RoomCount;
use App\RoomType;
use App\Section;
use App\SectionType;
use App\StageOfConstruction;
use App\StreetName;
use App\TechnologyBuilding;
use Intervention\Image\Facades\Image;
use Symfony\Component\DomCrawler\Crawler;

class WriteResidentComplexPlanningController extends Controller
{
    use ImageUploadTrait, Transliteration, ResidentialComplexMapping;
    const RESIDENT_COMPLEX = 'resident-complex-1.json';
    const MAPPING_VN_LUN = 'mapping_residential_complexes_vn_and_lun.json';
    const HTTPS = 'https://';
    const HTTPS_NOT_BACKSLASH = 'https:';
    const VN_RESIDENTIAL_COMPLEX_URL_PREFIX = "https://vn.com.ua/complex/";
    const CROP_X = 0;
    const CROP_Y = 35;
    const ROOM_TYPE_STUDIO = 'studio';
    const ROOM_TYPE_TWO_LEVEL = 'two_level';
    const ROOM_TYPE_MANY_LEVEL_LUN = 'дворівневої';
    const ASPECT_RATIO_IMAGE = 1.33333;
    const ASPECT_RATIO_BUILDING_PROCESS = 1.2967;
    const WATER_MARK_WIDTH_LUN = 86;
    const WATER_MARK_WIDTH_LUN_LARGE = 168;
    private $minPrice = 0;

    /**
     * @param $page
     */
    public function index()
    {
        //        self::regroupAllPricingSection();
//        $this->resizeImageSize();

        for ($i = 1; $i <= 12; $i++) {
            $file = 'resident-complex-' . $i . '.json';
            dump("Parce file $i");
            $dataResidentialComplexes = $this->getJsonFile($file);
            dump('start writing...');
            foreach ($dataResidentialComplexes as $key => $residentialComplexes) {
                $this->getResidentialComplex($residentialComplexes);
                dump('Save Residential complex success!');
            }
        }
    }

    public function getResidentialComplex(array $residentialComplexes)
    {
        foreach ($residentialComplexes as $key => $residentialComplex) {
            if ($residentialComplex->name == 'ЖК Avalon Up') {
//            if ($key >= 0) {
                dump($residentialComplex->name);
                $this->writeComplex($residentialComplex);
            }
        }
    }

    private function writeComplex($data): void
    {
        $residentComplex = ResidentialComplex::query()->where('name', $data->name)->first();
        if ($residentComplex) {
            try {
                $this->planing($data, $residentComplex);
            } catch (\Exception $ee) {
                dump($data);
                var_dump('planning error');
            }
        } else {
            var_dump("residential complex $data->name do not find");
        }
    }

    public function parseImagesFromVN($residentComplex)
    {
        $mappingResidentialComplexVnAndLun = $this->mappingRCList();
        foreach ($mappingResidentialComplexVnAndLun as $item) {
            if ($item['lun_name'] == $residentComplex->name) {
                $vnSlug = self::VN_RESIDENTIAL_COMPLEX_URL_PREFIX . $item['vn_slug'];
                $imageLinks = $this->parseVNResidentialComplexSinglePage($vnSlug);
                $this->saveResidentialComplexImage($imageLinks, $residentComplex);
            }
        }
    }

    public function parseVNResidentialComplexSinglePage($vnSlug)
    {
        $linksArray = [];
        $html = file_get_contents($vnSlug);
        $crawler = new Crawler(null, $vnSlug);
        $crawler->addHtmlContent($html, 'UTF-8');
        $sliderBlock = $crawler->filter('div.section--slider');
        $links = $sliderBlock->filter('a.building-view__gallery-img');
        foreach ($links as $link) {
            $link = $link->getAttribute('href');
            if (preg_match('/image/', $link)) {
                $linksArray[] = $link;
            }
        }

        return $linksArray;
    }

    public function saveResidentialComplexImage($links, $residentComplex)
    {
        foreach ($links as $key => $link) {
            $fileLink = self::HTTPS_NOT_BACKSLASH . $link;
            $file = file_get_contents(self::HTTPS_NOT_BACKSLASH . $link);
            $fileExtension = $this->fileExtension($file);
            $fileNameWithExtension = $this->transliteration($residentComplex->name) . $key . '.' . $fileExtension;
            $image = Image::make($file);
            $imageHeight = $image->getHeight();
            $imageWidth = $image->getWidth();
            $aspectRatio = $imageWidth / $imageHeight;
            if ($aspectRatio >= self::ASPECT_RATIO_IMAGE) {
                $parameters = $this->calculateAspectRatio($imageHeight);
                $image->crop($parameters['width'],
                    $parameters['height'])->save(public_path(env('UPLOAD_PATH')) . '/parser/' . $fileNameWithExtension);
                $this->saveImageCollection($residentComplex, $image, 'landscape_photo',
                    [$parameters['width'], $parameters['height']], $fileLink);
            }
        }
    }

    public function characteristic($residentialComplex, $characteristics)
    {
        $ignoredKeys = ["клас", "технологія будівництва", "опалення"];
        foreach ($characteristics as $key => $characteristic) {
            if (!in_array($key, $ignoredKeys)) {
                $residentialComplexCharacters = new ResidentialComplexCharacter();
                $residentialComplexCharacters->residental_complex_id = $residentialComplex->id;
                $residentialComplexCharacters->type = $key;
                $residentialComplexCharacters->value = $characteristic;
                $residentialComplexCharacters->save();
            }
        }

        return $residentialComplex;
    }

    public function classHousing($residentialComplex, $characteristic)
    {
        $class = "клас";
        if (isset($characteristic->$class)) {
            $classHousingValue = $characteristic->$class;
            $classHousingValueOptimaze = ucfirst($classHousingValue);
            $classHousing = ClassHousing::query()->where('name', '=', $classHousingValueOptimaze)->first();
            if ($classHousing) {
                $residentialComplex->class()->attach($classHousing->id);
            }
        }

        return $residentialComplex;
    }

    public function technologyBuilding($residentialComplex, $characteristic)
    {
        $technologyBuilding = "технологія будівництва";
        if (isset($characteristic->$technologyBuilding)) {
            $technologyBuildingValue = $characteristic->$technologyBuilding;
            $technologyBuildingValueOptimaze = ucfirst($technologyBuildingValue);
            $technologyBuildingObject = TechnologyBuilding::query()->where('name', '=',
                $technologyBuildingValueOptimaze)->first();
            if ($technologyBuildingObject) {
                $residentialComplex->technology_building()->attach($technologyBuildingObject->id);
            }
        }

        return $residentialComplex;
    }

    public function heating($residentialComplex, $characteristic)
    {
        $heatingKey = "опалення";
        if (isset($characteristic->$heatingKey)) {
            $heatingValue = $characteristic->$heatingKey;
            $heatingKeyValueOptimaze = ucfirst($heatingValue);
            $explodeHeatingValue = explode(' ', $heatingKeyValueOptimaze);
            if (count($explodeHeatingValue) > 0) {
                $heatingFirsetElement = $explodeHeatingValue[0];
                $heating = Heating::query()->where('name', '=', $heatingFirsetElement)->first();
                if ($heating) {
                    $residentialComplex->heating()->attach($heating->id);
                }
            }
        }

        return $residentialComplex;
    }

    public function calculateAspectRatio($height)
    {
        $newWidth = $height * self::ASPECT_RATIO_IMAGE;

        return ['width' => round($newWidth), 'height' => round($height)];
    }

    private function getPlanImage($imageUrl, $imageName)
    {
        try {
            $file = file_get_contents($imageUrl);
        } catch (\Exception $exception) {
            dump($imageUrl);
            dump('iamge was not exist');

            return null;
        }
        $file = file_get_contents($imageUrl);
        $time = time();

        $imageSize = $this->imagePlanningSize($file);

        $smallSize = $this->saveImagePlanning($imageUrl, ImageSize::PLANNING, ImageSize::PLANNING_WEBP,
            [$imageSize['width'], $imageSize['height']], $imageName, $file, $time);

        $nativeSize = $this->saveImagePlanning($imageUrl, ImageSize::PLANNING_FULL, ImageSize::PLANNING_FULL_WEBP, [],
            $imageName, $file, $time);

//           $fullSize = $this->saveImagePlanning($imageUrl, ImageSize::PLANNING_BIG, ImageSize::PLANNING_BIG_WEBP,ImageSize::PLANING_BIG_SIZE, $imageName, $file);

        return $smallSize;
    }

    private function getRoomType($type)
    {
        if ($type == self::ROOM_TYPE_STUDIO || $type == self::ROOM_TYPE_TWO_LEVEL) {
            $roomType = RoomType::whereCode($type)->first();
        }

        return isset($roomType) ? $roomType->id : null;
    }

    public function getBuildingRoomCount($code)
    {
        if (!empty($code)) {
            $roomCount = RoomCount::query()->where('code', '=', $code)->first();
        }

        return isset($roomCount) ? $roomCount->id : null;
    }

    /**
     * @param $data
     * @param ResidentialComplex $residentialComplex
     */
    private function planing($data, $residentialComplex)
    {
        if (is_array($data->planning)) {
            $buildingPlannings = $data->planning;
        } elseif ($data->planning instanceof \stdClass) {
            $buildingPlannings = [$data->planning];
            foreach ($data->planning as $pl) {
                if ($pl instanceof \stdClass) {
                    $buildingPlannings = $data->planning;
                } else {
                    $buildingPlannings = [$data->planning];
                    break;
                }
            }
        }
        if (is_array($data->section)) {
            $buildingSections = $data->section;
        } elseif ($data->planning instanceof \stdClass) {
            if (isset($data->planning[0])) {
                $buildingSections = [$data->section];
            }
        }
        foreach ($buildingPlannings as $buildingPlanning) {
            $section = $this->createSection($buildingPlanning, $residentialComplex, $buildingSections);
            $sectionListRC = $residentialComplex->sections;
            $isSectionExist = false;
            $currentSection = null;
            foreach ($sectionListRC as $sectionRC) {
                if ($sectionRC->name == $section->name) {
                    $isSectionExist = true;
                    $currentSection = $sectionRC;
                }
            }
            if ($isSectionExist == true) {
                $currentSection->update(['is_planning' => 1]);
                $planning = $this->createSectionPlanning($currentSection, $buildingPlanning, $data->building_price,
                    $residentialComplex);
            } else {
                dump($section->name . ' + ' . $residentialComplex->name);
                $section->save();
                $planning = $this->createSectionPlanning($section, $buildingPlanning, $data->building_price,
                    $residentialComplex);
            }
        }
    }

    public function checkIsStdClassAndConvertToArray($data)
    {
        $array = [];
        if (is_array($data)) {
            $array = $data;
        } elseif ($data->planning instanceof \stdClass) {
            $array = [$data];
        }

        return $array;
    }

    public function createSection($data, $residentialComplex, $buildingSections)
    {
        $building = isset($data->building) ? $data->building->title : "";
        if (!empty($building)) {
            $buildingExplode = explode(" ", $building);
            $buildingExplodeCount = count($buildingExplode);
            $buildingType = count($buildingExplode) > 0 ? $buildingExplode[0] : "";
            $sectionTypes = SectionType::all();
            $type = $sectionTypes->first();
            foreach ($sectionTypes as $sectionType) {
                if ($sectionType->type == $buildingType) {
                    $type = $sectionType;
                }
            }
            $parsedSectionInfo = $this->parseSectionInfo($buildingSections);
            $buildingNumber = count($buildingExplode) >= 2 ? $buildingExplode[$buildingExplodeCount - 1] : null;
            $buildingFloor = isset($data->flor) ? $data->flor : null;
            $quarterly = $this->getSectionQuarterly($buildingNumber, $parsedSectionInfo);
            $stageOfConstruction = $this->getSectionStageOfConstruction($buildingNumber, $parsedSectionInfo);
            $section = new Section();
            $section->number = $buildingNumber;
            $section->name = isset($data->building) ? $data->building->title : "";
            $section->count_of_floor = $buildingFloor;
            $section->section_type_id = $type->id;
            $section->residental_complex_id = $residentialComplex->id;
            $section->quarterly_finish_id = $quarterly ? $quarterly->id : null;
            $section->is_planning = 1;
            $section->date_finish_buildiing = $this->getSectionDate($buildingNumber, $parsedSectionInfo);
            $section->stage_of_construction_id = $stageOfConstruction ? $stageOfConstruction->id : null;
            $section->stage_of_construction_id = $stageOfConstruction ? $stageOfConstruction->id : null;

//            $section->save();
            return $section;
        }
    }

    public function createSectionPlanning($section, $building, $buildingPrices, $residentialComplex)
    {
        $regroupedPlanning = $this->regroupPlanningWithType($building);
        $section = $section ? $section : null;
        if (!$section) {
            var_dump("section was not created");
        }
        $counter = 0;
        foreach ($regroupedPlanning['plannings'] as $planningsKey => $item) {
            foreach ($item['planning'] as $planningKey => $plan) {
                $imageName = $planningsKey . $planningKey . $residentialComplex->code;
                $planning = new Planning();
                $planning->section_id = $section ? $section->id : null;
                $planning->space = (double)$plan['space'];
                $planning->amount_of_apartment = 1;
                $planning->room_id = $this->getBuildingRoomCount($item['room_count']);
                $planning->room_type_id = $this->getRoomType($plan['type']);
                $planning->image = $this->getPlanImage($plan['image'], $imageName);
                $costOrIsSold = $this->getPlanningPricePerSquareMeter($planning, $section, $buildingPrices);
                $planning->cost_per_square_meter = $costOrIsSold == 'sold' ? null : (double)$costOrIsSold;
                $planning->is_sold = $plan['is_sold'] == true ? 1 : 0;
                if (!empty($planning->space) && !empty($planning->cost_per_square_meter)) {
                    $total = $planning->space * $planning->cost_per_square_meter;
                    $planning->total_cost = $total;
                    if ($counter == 0) {
                        /** @var ResidentialComplex $residentialComplex */
                        $residentialComplex->min_price = $total;
                        $residentialComplex->update();
                        $counter++;
                    }
                }
                $planning->save();
            }
        }
    }

    public function regroupPlanningWithType($building)
    {
        $buildingPlanningRooms = $this->checkIsStdClassAndConvertToArray($building->rooms);
        $buildingPlanningRoomFeature = $this->checkIsStdClassAndConvertToArray($building->feature);
        $roomPlannings = [
            'building' => $building->building
        ];
        foreach ($buildingPlanningRooms as $buildingKey => $buildingPlanningRoom) {
            $roomNumber = isset($buildingPlanningRoom->room_count) ? $buildingPlanningRoom->room_count->value : null;
            $planningsOfRoomCount = isset($buildingPlanningRoom->planning) ? $buildingPlanningRoom->planning : [];
            $roomPlannings['plannings'][$buildingKey] = [
                'room_count' => $roomNumber
            ];
            foreach ($planningsOfRoomCount as $key => $planningsOfRoom) {
                $roomPlannings['plannings'][$buildingKey]['planning'][] = [
                    'image' => self::HTTPS_NOT_BACKSLASH . $planningsOfRoom->image,
                    'space' => $planningsOfRoom->space,
                    'type' => count($buildingPlanningRoomFeature) > 0 ? $this->checkPlanningRoomType($roomNumber,
                        $planningsOfRoom, $buildingPlanningRoomFeature) : null,
                    'is_sold' => $planningsOfRoom->is_sold
                ];
            }
        }

        return $roomPlannings;
    }

    public function checkPlanningRoomType($roomNumber, $planningsOfRoom, $buildingPlanningRoomFeatures)
    {
        $type = null;
        foreach ($buildingPlanningRoomFeatures as $buildingRoomPlanningFeature) {
            $roomPlanningFeatureNumber = isset($buildingRoomPlanningFeature->room_count) ? $buildingRoomPlanningFeature->room_count->value : null;
            if ($roomPlanningFeatureNumber = $roomNumber) {
                $listPlanningOfRoomFeature = isset($buildingRoomPlanningFeature->planning) ? $buildingRoomPlanningFeature->planning : [];
                foreach ($listPlanningOfRoomFeature as $planningOfRoomFeature) {
                    if ($planningsOfRoom->alt == $planningOfRoomFeature->alt) {
                        if (preg_match('/дворівневої/', $planningsOfRoom->alt)) {
                            return self::ROOM_TYPE_TWO_LEVEL;
                        } else {
                            return self::ROOM_TYPE_STUDIO;
                        }
                    }
                }
            }
        }

        return null;
    }

    public function getSectionQuarterly($buildingTitle, $parsedSectionInfo)
    {
        $quarterlies = Quarterly::all();
        foreach ($parsedSectionInfo as $section) {
            if ($section['buildingNumber'] == $buildingTitle) {
                foreach ($quarterlies as $quarterly) {
                    if ($quarterly->code == $buildingTitle) {
                        return $quarterly;
                    }
                }
            }
        }

        return null;
    }

    public function getSectionDate($buildingTitle, $parsedSectionInfo)
    {
        foreach ($parsedSectionInfo as $section) {
            if ($section['buildingNumber'] == $buildingTitle && !empty($section['year'])) {
                return $section['year'];
            }
        }

        return null;
    }

    public function getSectionStageOfConstruction($buildingTitle, $parsedSectionInfo)
    {
        foreach ($parsedSectionInfo as $section) {
            if ($section['buildingNumber'] == $buildingTitle && !empty($section['stageOfConstruction'])) {
                return $this->getStageOfConstructionFromLunStage($section['stageOfConstruction']);
            }
        }

        return null;
    }

    public function getPlanningPricePerSquareMeter($planning, $section, $buildingPrices)
    {
        $buildingNumber = $section->number;
        foreach ($buildingPrices as $buildingPriceElement) {
            $buildingNumbers = $this->getNumberFromBuildingPriceElement($buildingPriceElement);
            if (count($buildingPrices) == 1) {
                $buildingNumbers = [1];
            }
            foreach ($buildingNumbers as $buildingNumber) {
                if ($buildingNumber == $section->number) {
                    foreach ($buildingPriceElement->price as $roomCountPrice) {
                        $isSold = $this->buildingPriceIsSoldParse($roomCountPrice);
                        if ($isSold != 'sold') {
                            if ($roomCountPrice->room == 'Дворівневі') {
                                if (!empty($planning->room_type_id) && $planning->room_type_id == 2) {
                                    return $this->buildingPricePerMeterParse($roomCountPrice, $planning);
                                }
                            } else {
                                $explodeRoomCount = explode("-", $roomCountPrice->room);
                                $roomCount = count($explodeRoomCount) > 0 ? $explodeRoomCount[0] : '';
                                if ($roomCount == $planning->room_id) {
                                    return $this->buildingPricePerMeterParse($roomCountPrice, $planning);
                                }
                            }
                        } else {
                            return $isSold;
                        }
                    }
                }
            }
        }

        return null;
    }

    public function buildingPriceIsSoldParse($roomCountPrice)
    {
        if ($roomCountPrice->full_price == 'продані') {
            return 'sold';
        }

        return '';
    }

    public function buildingPricePerMeterParse($roomCountPrice, $planning)
    {
        try {
            $costPerMeterFromLun = $roomCountPrice->price_per_square_meter;
            if (preg_match('/—/', $costPerMeterFromLun)) {
                $fewCostPerMeterLun = explode('—', $costPerMeterFromLun);
                $chipperCost = count($fewCostPerMeterLun) > 0 ? trim($fewCostPerMeterLun[0]) : [];
                $cost = strlen($chipperCost) > 1 ? intval(preg_replace('/[^0-9]/', '', $chipperCost)) : 0;
            } elseif (preg_match('/грн/', $costPerMeterFromLun)) {
                $fewCostPerMeterLun = explode(' ', $costPerMeterFromLun);
                $chipperCost = count($fewCostPerMeterLun) > 0 ? trim($fewCostPerMeterLun[0]) : [];
                $cost = strlen($chipperCost) > 1 ? intval(preg_replace('/[^0-9]/', '', $chipperCost)) : 0;
            }
        } catch (\Exception $exception) {
            var_dump($roomCountPrice);
            var_dump('price for planning was not fount');
        }

        return isset($cost) ? $cost : null;
    }

    public function getNumberFromBuildingPriceElement($buildingPrice)
    {
        $buildingNumbers = [];
        $buildingNumberElement = $buildingPrice->header;
        if (preg_match('/будинок,/', $buildingNumberElement)) {
            $buildingNumberList = explode(',', $buildingNumberElement);
            foreach ($buildingNumberList as $value) {
                $value = trim($value);
                $buildingNumberExplode = explode(' ', $value);
                $buildingNumber = count($buildingNumberExplode) > 0 ? $buildingNumberExplode[0] : "";
                $buildingNumbers[] = $buildingNumber;
            }
        } elseif (strpos($buildingNumberElement, ' ')) {
            $buildingNumberExplode = explode(' ', $buildingNumberElement);
            $buildingNumber = count($buildingNumberExplode) > 0 ? $buildingNumberExplode[0] : "";
            $buildingNumbers = [$buildingNumber];
        }

        return $buildingNumbers;
    }

    public function getStageOfConstructionFromLunStage($stage)
    {
        return $stageOfConstruction = StageOfConstruction::query()->where('name', '=', $stage)->first();
        //        $build = "Збудовано";
//        $plan = "Планується";
//        $beingBuilt = "Будується";
//        $inPlanLun = "в проекті";
//        $buildLun = "збудований";
//        $beingBuiltLun = "будується";
//        $preparatoryWorkLun = "підготовчі роботи";
//        $stageOfConstructionMapping = [
//            $inPlanLun => $plan,
//            $preparatoryWorkLun => $plan,
//            $buildLun => $build,
//            $beingBuiltLun => $beingBuilt
//        ];
//        if (array_key_exists($stage, $stageOfConstructionMapping)) {
//        }
//        return null;
    }

    public function parseSectionInfo($buildingSections)
    {
        $data = [];
        foreach ($buildingSections as $buildingSection) {
            // quarterly
            if (isset($buildingSection->quarterly) && preg_match('/:/', $buildingSection->quarterly)) {
                $quarterlyExploded = explode(":", $buildingSection->quarterly);
                $dateAndQuarterly = count($quarterlyExploded) >= 2 ? trim($quarterlyExploded[1]) : '';
                if (preg_match('/кв./', $dateAndQuarterly)) {
                    $dateAndQuarterlyExplode = explode(' ', $dateAndQuarterly);
                    $year = count($dateAndQuarterlyExplode) > 2 ? $dateAndQuarterlyExplode[2] : '';
                    $quarterly = count($dateAndQuarterlyExplode) > 2 ? $dateAndQuarterlyExplode[0] : '';
                }
            } elseif (isset($buildingSection->quarterly) && preg_match('/кв./', $buildingSection->quarterly)) {
                $quarterlyExploded = explode("кв.", $buildingSection->quarterly);
                $year = count($quarterlyExploded) >= 1 ? trim($quarterlyExploded[1]) : '';
                $quarterlyWithText = count($quarterlyExploded) >= 1 ? trim($quarterlyExploded[0]) : '';
                $quarterlyExplode = explode(" ", $quarterlyWithText);
                $quarterlyCount = count($quarterlyExplode) > 1 ? count($quarterlyExplode) : 0;
                $quarterly = $quarterlyCount > 0 ? $quarterlyExplode[$quarterlyCount - 1] : '';
            }
            // stage of construction
            $status = $this->checkStageOfConstructionFromLum($buildingSection->status);
            $numberOfBuilding = $this->buildingNumberFromLum($buildingSection->status);
            if (isset($buildingSection->status) && !empty($status) && !empty($numberOfBuilding)) {
//                $statusExplode = explode("—", $buildingSection->status);
                $stageOfConstraction = $status;
//                $buiding = count($statusExplode) > 1 ? trim($statusExplode[0]) : '';
                $buiding = $numberOfBuilding;
                if (strpos($buiding, " ")) {
                    $buildingNumberExplode = explode(' ', $buiding);
                    $buildingNumber = count($buildingNumberExplode) > 0 ? $buildingNumberExplode[0] : '';
                }
            } else {
                $stageOfConstraction = $buildingSection->status;
            }
            if (!isset($buildingNumber) && count($buildingSections) == 1) {
                $buildingNumber = 1;
            }
            $data[] = [
                'year' => isset($year) ? $year : '',
                'quarterly' => isset($quarterly) ? $quarterly : '',
                'stageOfConstruction' => isset($stageOfConstraction) ? $stageOfConstraction : '',
                'buildingNumber' => isset($buildingNumber) ? $buildingNumber : '',
                'building' => isset($buiding) ? $buiding : ''
            ];
        }

        return $data;
    }

    public function checkStageOfConstructionFromLum($status)
    {
        if (preg_match('/Будується/', $status)) {
            return 'Будується';
        } else {
            if (preg_match('/В проекті/', $status) || preg_match('/підготовчі роботи/', $status)) {
                return 'Планується';
            } else {
                if (preg_match('/збудована/', $status) || preg_match('/Збудовано/', $status)) {
                    return 'Збудовано';
                }
            }
        }

        return '';
    }

    public function buildingNumberFromLum($status)
    {
        if (preg_match('/Будується/', $status)) {
            return trim(str_replace('Будується', '', $status));
        } elseif (preg_match('/В проекті/', $status)) {
            return trim(str_replace('В проекті', '', $status));
        } elseif (preg_match('/збудована/', $status)) {
            return trim(str_replace('збудована', '', $status));
        } elseif (preg_match('/підготовчі роботи/', $status)) {
            return trim(str_replace('підготовчі роботи', '', $status));
        } elseif (preg_match('/Збудовано/', $status)) {
            return trim(str_replace('Збудовано', '', $status));
        }

        return '';
    }

    private function checkIdSection($data, $key)
    {
        $section = isset($data->price->queues[$key]) ? $data->price->queues[$key] : null;
        if (!$section) {
            return 0;
        }
        $allSection = "Весь комплекс";
        $idSection = 0;
        if (!($section->title == $allSection)) {
            $sectionExplode = explode("—", $section->title);
            if (strpos($sectionExplode[0], 'дом') !== false || strpos($sectionExplode[0], 'очередь') !== false) {
                $search1 = "секции";
                $search2 = "секция";
                if (!(preg_match("/{$search1}/i", $sectionExplode[0])) || preg_match("/{$search2}/i",
                        $sectionExplode[0])) {
                    $idSection = 1;
                }
            }
            if (strpos($sectionExplode[0], 'секции') !== false || strpos($sectionExplode[0], 'секциия') !== false) {
                $idSection = 2;
            }

            return $idSection;
        }

        return 0;
    }

    private function getPlanCost($getPricePlan)
    {
        $object = '12';
        if (isset($getPricePlan->$object)) {
            $search = "тис.";
            $search2 = "млн";
            if (preg_match("/{$search}/i", $getPricePlan->$object)) {
                return (preg_replace("/[^0-9]/", '', $getPricePlan->$object)) * 1000;
            } else {
                if (preg_match("/{$search2}/i", $getPricePlan->$object)) {
                    return preg_replace("/[^0-9]/", '', $getPricePlan->$object) * 10000;
                }
            }
        }

        return 0;
    }

    private function getCostPerSquareMeter($getPriceSquare)
    {
        $object = '75';
        if (isset($getPriceSquare->$object)) {
            $price = explode("—", $getPriceSquare->$object);

            return preg_replace("/[^0-9]/", '', trim($price[0]));
        }

        return 0;
    }

    private function writeSection($residentComplex, $data)
    {
        $sections = $data->section;
        for ($i = 0; $i < $this->getBuldingCount($data->characteristic); $i++) {
            $sectionItem = isset($sections[$i]) ? $sections[$i] : collect($sections)->last();
            $section = Section::create($this->createSection($residentComplex, $i, $sectionItem, $data));
            $planing = $this->writePlaning($residentComplex, $data, $section->id);
        }
    }

    private function createResidentialComplex($data)
    {
        $check = $data;
        $a = $check;
        try {
            $code = $this->transliteration($data->name);
        } catch (\Exception $e) {
            var_dump('transiteration');
            var_dump($data);
        }
        try {
            $buidingData = $this->getBuldingCount($data->characteristic);
        } catch (\Exception $e) {
            var_dump('getBuldingCount bad parameter');
            var_dump($data);
        }
        try {
            $roomCount = $this->getRoomCount($data->characteristic);
        } catch (\Exception $e) {
            var_dump('roomCount bad parameter');
            var_dump($data);
        }
        try {
            $developer = $this->getDeveloper($data->developer);
        } catch (\Exception $e) {
            var_dump('developer bad parameter');
            var_dump($data);
        }
        try {
            $city = $this->getCity($data->city);
            $cityName = $city ? $city->name . ", " : '';
        } catch (\Exception $e) {
            var_dump('city bad parameter');
            $cityName = '';
        }
        try {
            $district = $this->getDistrict($data->district);
            $districtName = $district ? $district->name . " р-н, " : '';
        } catch (\Exception $e) {
            var_dump('district bad parameter');
            $districtName = '';
        }
        $residental = [
            'name' => $data->name,
            'code' => isset($code) && !empty($code) ? $code : "",
            'site_link' => self::HTTPS . $data->siteLink,
            'main_page_priority' => null,
            'res_com_page_priority' => null,
//            'min_price' => $this->getPriceRoom($getPriceRoom),
            'date_putting_into_operation' => null, //?
            'building_count' => isset($buidingData) && !empty($buidingData) ? $buidingData : '',
            'room_count' => isset($roomCount) && !empty($roomCount) ? $roomCount : '',
            'room_count_date' => null,//?
            'is_credit' => isset($data->credit) && $data->credit == true ? 1 : 0,
            'location_address' => $cityName . $districtName . $data->street,
            'location_latitude' => isset($data->cords->latitude) ? $data->cords->latitude : null,
            'location_longitude' => isset($data->cords->longitude) ? $data->cords->longitude : null,
            'developer_id' => isset($developer) ? $developer : null,
            'city_id' => isset($city) ? $city->id : null,
            'district_id' => isset($district) ? $district->id : null,
            'street_name_id' => $this->getStreetName($data->street),
            'street_number' => $this->getStreetNumber($data->street),
            'stage_of_construction_id' => $this->getStageOfConstraction($data->status_build),
            'quarterly_putting_into_operation_id' => 1, //?
            'center_distance' => 1
        ];

        return $residental;
    }

    public function getCity($cityName)
    {
        $city = City::where('name', 'LIKE', '%' . $cityName . '%')->first();
        if (!$city) {
            return null;
        }

        return $city;
    }

    private function getStageOfConstraction(array $states)
    {
        $bilded = "збудований";
        $vdomaBilded = "Збудовано";
        $stanFirstElement = isset($states[0]) ? $states[0] : null;
        $stan = isset($states[1]) ? trim($states[1]) : $stanFirstElement;
        if ($stan) {
            $stageOfConstruction = $this->getStageOfConstructionFromLunStage($stan);
        }

        return isset($stageOfConstruction) ? $stageOfConstruction->id : null;
    }

    private function getBuldingCount($characteristic)
    {
        $houses = "будинків";

        return isset($characteristic->$houses) ? $characteristic->$houses : 0;
    }

    private function getRoomCount($characteristic)
    {
        $klass = "Клас";
        $floor = "Поверховість";
        $tehcnologiBuild = "Технологія будівництва";
        $wall = "Стіни";
        $warm = "Утеплення";
        $heating = "Опалення";
        $heightWall = "Висота стелі";
        $amountApartments = "кількість квартир";
        $parking = "Паркінг";
        $state = "Стан квартири";
        $closeTerritory = "Закрита територія";
        if (isset($characteristic->$amountApartments)) {
            $roomCountExplode = explode(' ', $characteristic->$amountApartments);
            $roomCount = count($roomCountExplode) > 0 ? $roomCountExplode[0] : 0;
        }

        return isset($roomCount) ? $roomCount : null;
    }

    private function getStreet(string $district)
    {
        $name = $this->getReplaceStreetName($this->myTrim($district));
        $street = StreetName::where('name', 'LIKE', '%' . $name . '%')->first();
        if (!$street) {
            return null;
        }

        return $street->id;
    }

    public function getStreetName($address)
    {
        $explodeFullAddress = explode('.', $address);
        $address = count($explodeFullAddress) > 1 ? trim($explodeFullAddress[1]) : '';
        $explodeStreetName = !empty($address) > 0 ? explode(',', $address) : [];
        $streetName = count($explodeStreetName) > 0 ? trim($explodeStreetName[0]) : "";
        if (!empty($streetName)) {
            $street = StreetName::where('name', 'LIKE', '%' . $streetName . '%')->first();
            if (!$street) {
                return null;
            }

            return $street->id;
        }

        return null;
    }

    public function getStreetNumber($address)
    {
        $explodeFullAddress = explode('.', $address);
        $address = count($explodeFullAddress) > 1 ? trim($explodeFullAddress[1]) : '';
        $explodeStreetName = !empty($address) > 0 ? explode(',', $address) : [];
        $streetNumber = count($explodeStreetName) > 1 ? trim($explodeStreetName[1]) : "";

        return $streetNumber;
    }

    private function getDistrict(string $district)
    {
        $name = $this->getReplaceDistrictName($district);
        $districtName = District::where('name', 'LIKE', '%' . $name . '%')->first();
        if (!$districtName) {
            return null;
        }

        return $districtName;
    }

    private function getDeveloper($developerName)
    {
        if (is_string($developerName)) {
            $developer = Developer::query()->where('developers.name', $developerName)->first();
            if (!$developer) {
                return null;
            } else {
                return $developer->id;
            }
        }

        return null;
    }

    private function getPriceRoom(array $priceRooms): string
    {
        $object = '12';
//
        if (isset($priceRooms[0]->$object)) {
            return preg_replace("/[^0-9]/", '', $priceRooms[0]->$object);
        }

        return "";
    }

    private function getReplaceDistrictName(string $string): string
    {
        $pattern = "/ р-н/";

        return preg_replace($pattern, "", $string);
    }

    private function getReplaceStreetName(string $string): string
    {
        $pattern = "/ вул./";

        return preg_replace($pattern, "", $string);
    }

    private function getJsonFile($filename, $assoc = false)
    {
        $fileContent = file_get_contents(public_path() . '/parser/' . $filename);
        $decode = json_decode($fileContent, $assoc);

        return $decode;
    }

    private function myTrim($str)
    {
        return trim(preg_replace('/[[:cntrl:]]/', '', $str));
    }

    private function saveProcessBuildPhotoMediaImage($courseOfConstruction, $imageLinks, $name)
    {
        foreach ($imageLinks as $key => $imageLink) {
            if (($key == 0 || $key == 1 || $key == 3) && isset($imageLink['normal']) && isset($imageLink['large'])) {
                $normalSizeImageLink = $imageLink['normal'];
                $largeSizeImageLink = $imageLink['large'];
                $fileLink = self::HTTPS_NOT_BACKSLASH . $largeSizeImageLink;
                $file = file_get_contents(self::HTTPS_NOT_BACKSLASH . $largeSizeImageLink);
                $fileExtension = $this->fileExtension($file);
                $fileNameWithExtension = $this->transliteration($name) . $courseOfConstruction->id . $key . '.' . $fileExtension;
                $image = Image::make($file);
                $imageHeight = $image->getHeight();
                $imageWidth = $image->getWidth();
                $aspectRatio = $imageWidth / $imageHeight;
                if ($aspectRatio >= self::ASPECT_RATIO_BUILDING_PROCESS) {
                    $parameters = $this->calculateBRCAspectRatio($imageWidth, $imageHeight);
                    $image->crop($parameters['width'], $parameters['height'], 0,
                        0)->save(public_path(env('UPLOAD_PATH')) . '/parser_build_process/' . $fileNameWithExtension);
                    $this->saveImageCollection($courseOfConstruction, $image, 'images',
                        [$parameters['width'], $parameters['height']], $fileLink);
                }
            }
        }
    }

    public function calculateBRCAspectRatio($newWidth, $imageHeight)
    {
        $newWidth = $newWidth - self::WATER_MARK_WIDTH_LUN_LARGE;

        return ['width' => round($newWidth), 'height' => round($imageHeight)];
    }

    public function calculateAspectRatioBuildProcess($height, $width)
    {
        $newWidth = $width - self::WATER_MARK_WIDTH_LUN;
        $newHeight = $newWidth / self::ASPECT_RATIO_BUILDING_PROCESS;

        return ['width' => round($newWidth), 'height' => round($newHeight)];
    }

    private function convertDate($parameters)
    {
        if (isset($parameters['month']) && isset($parameters['year'])) {
            return date('d.m.Y', strtotime('01' . '-' . $parameters['month'] . '-' . $parameters['year']));
        }

        return date('d.m.Y');
    }

    public function haversineGreatCircleDistance(
        $latitudeFrom,
        $longitudeFrom,
        $latitudeTo,
        $longitudeTo,
        $earthRadius = 6371000
    ) {
        // convert from degrees to radians
        $latFrom = deg2rad($latitudeFrom);
        $lonFrom = deg2rad($longitudeFrom);
        $latTo = deg2rad($latitudeTo);
        $lonTo = deg2rad($longitudeTo);
        $latDelta = $latTo - $latFrom;
        $lonDelta = $lonTo - $lonFrom;
        $angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) + cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)));

        return ($angle * $earthRadius);
    }

    private function updateDistance(ResidentialComplex $residentComplex)
    {
        /** @var City $city */
        $city = $residentComplex->city()->first() ? $residentComplex->city()->first() : null;
        $residentialComplexLocationLatitude = $residentComplex->location_latitude;
        $residentialComplexLocationLongitude = $residentComplex->location_longitude;
        if (isset($residentialComplexLocationLongitude) && isset($residentialComplexLocationLatitude) && $city) {
            if ($city->center_latitude && $city->center_longitude) {
                $distance = $this->haversineGreatCircleDistance($residentialComplexLocationLatitude,
                    $residentialComplexLocationLongitude, $city->center_latitude, $city->center_longitude);
                if ($distance > 0) {
                    $kilometers = $distance / 1000;
                    $residentComplex->center_distance = $kilometers;
                    $residentComplex->update();
                }
            }
        }
    }

    private function writeProcessBuildRc($residentComplex, $processBuild)
    {
        $decodeArray = json_decode(json_encode($processBuild), true);
        $name = $residentComplex->name;
        foreach ($decodeArray as $year => $processBuildYear) {
            foreach ($processBuildYear as $month => $processBuildMonth) {
                $data = $this->createCourseOfConstruction($residentComplex, [
                    'year' => $year,
                    'month' => $month
                ]);
                $courseOfConstruction = CourseOfConstruction::create($data);
                $this->saveProcessBuildPhotoMediaImage($courseOfConstruction, $processBuildMonth, $name);
            }
        }
    }

    private function createCourseOfConstruction($residentComplex, $parameters)
    {
        $course = [
            'youtube_link' => null,
            'report_date' => $this->convertDate($parameters),
            'residental_complex_id' => $residentComplex->id
        ];

        return $course;
    }

    private function getTwoFloor(array $data, $floors)
    {
        $sortPlans = [];
        foreach ($data as $key => $values) {
            foreach ($values as $keyItem => $items) {
                foreach ($items as $item) {
                    foreach ($floors as $floorItems) {
                        foreach ($floorItems as $floorItem) {
                            if ($floorItem->text == $item->text) {
                                $sortPlans[$key][$keyItem][] = $floorItem;
                            }
                        }
                    }
                }
            }
        }

        return $sortPlans;
    }

    private function getDropDownFloorHeader($data)
    {
        $plansCollections = $data->dropDownWithHeaderResult;
        $plans = [];
        $twoFloorHouse = [];
        foreach ($plansCollections as $key => $collection) {
            $twoFloorHouse[] = collect($collection)->last();
            foreach ($collection as $values) {
                foreach ($values as $value) {
                    foreach ($value as $item) {
                        if (is_array($item)) {
                            $plans[$key][] = $item;
                        }
                    }
                }
            }
        }
        $plans['floors'] = $this->getTwoFloor($plans, $twoFloorHouse);

        return $plans;
    }

    private function createPlaning($data, $keRooms, $section, $plan)
    {
        $getPriceRoom = isset($data->building_price[0]->table[0][$keRooms]) ? $data->building_price[0]->table[0][$keRooms] : [];
        $planText = isset($plan->text) ? $plan->text : $plan[0]->text;
        $planImage = isset($plan->image) ? $plan->image : $plan[0]->image;
        $planSize = isset($plan->size) ? $plan->size : $plan[0]->size;
        $planImage = $this->getPlanImage(self::HTTPS_NOT_BACKSLASH . $planImage);
        $planing = [
            'name' => $planText,
            'image' => isset($planImage) ? $planImage->basename : null,
            'cost_per_square_meter' => $this->getCostPerSquareMeter($getPriceRoom),
            'space' => trim(preg_replace("/м²/", "", $planSize)),
            'total_cost' => $this->getPlanCost($getPriceRoom),
            'room_id' => ($keRooms + 1),
            'room_type_id' => $this->getRoomType($keRooms),
            'section_id' => $section,
            'count_of_floor' => null,
            'is_sold' => 0,
            'amount_of_apartment' => null,
        ];
        dump('first plan create ');

        return $planing;
    }

    public function imageWebpEncode()
    {
        $plannings = Planning::all();
        foreach ($plannings as $planning) {
            $planningImagePath = $planning->image;
            $pathPng = public_path(env('UPLOAD_PATH') . '/' . ImageSize::PLANNING);
            $pathWebp = public_path(env('UPLOAD_PATH') . '/' . ImageSize::PLANNING_WEBP);
            $img = $pathPng . '/' . $planningImagePath;
            $file = file_get_contents($img);
            Image::make($file)->encode('webp')->save($pathWebp . '/' . $planningImagePath . ImageSize::IMAGE_WEBP);
        }
    }

    public static function regroupAllPricingSection()
    {
        $pricing = Price::query()->whereNull('deleted_at')->get();
        /** @var Price $price */
        foreach ($pricing as $price) {
            /** @var Section $section */
            $section = $price->section;
            if ($section) {
                $section->update([
                    'is_pricing' => 1
                ]);
            }
        }
    }

    public function resizeImageSize()
    {
        $pathPngFull = public_path(env('UPLOAD_PATH') . '/' . \App\Helpers\ImageSize::PLANNING_FULL);
        $pathPng = public_path(env('UPLOAD_PATH') . '/' . \App\Helpers\ImageSize::PLANNING);
        $pathWebp = public_path(env('UPLOAD_PATH') . '/' . \App\Helpers\ImageSize::PLANNING_WEBP);
        $plannings = \App\Planning::all();

        if (!file_exists($pathPng) && !file_exists($pathWebp)) {
            mkdir($pathPng, 0775, true);
            mkdir($pathWebp, 0775, true);
        }

        foreach ($plannings as $planning) {
            $imageName = $planning->image;
            $imageWithPath = $pathPngFull . '/' . $imageName;
            if (file_exists($imageWithPath)) {
                try {
                    $file = file_get_contents($imageWithPath);
                } catch (\Exception $exception) {
                    dump($imageName);
                    dump($exception);
                }
            }

            $imageSize = $this->imagePlanningSize($file);

            $imageNameWithPath = $pathPng . '/' . $imageName;
            Image::make($file)->resize($imageSize['width'], $imageSize['height'])->save($imageNameWithPath);

            $imageWebpNameWithPath = $pathWebp . '/' . $imageName . ImageSize::IMAGE_WEBP;
            Image::make($file)->encode('webp')->resize($imageSize['width'], $imageSize['height'])
                ->save($imageWebpNameWithPath);
        }
    }

    public function changeNameImage(Request $request)
    {
        $pathPng = public_path(env('UPLOAD_PATH') . '/' . \App\Helpers\ImageSize::PLANNING);
        $pathPngFull = public_path(env('UPLOAD_PATH') . '/' . \App\Helpers\ImageSize::PLANNING_FULL);
        $pathPngFullWebp = public_path(env('UPLOAD_PATH') . '/' . \App\Helpers\ImageSize::PLANNING_FULL_WEBP);
        $plannings = \App\Planning::all();
        foreach ($plannings as $planning) {
            $imageName = $planning->image;
            $imageWithPath = $pathPngFull . '/' . $imageName;
            $imageWebpWithPath = $pathPngFullWebp . '/' . $imageName . ".webp";
            if (!file_exists($imageWithPath) || !file_exists($imageWebpWithPath)) {
                $explodeName = explode("-", $imageName);
                $time = count($explodeName) > 0 ? (int)$explodeName[0] : "";
                if (!empty($time)) {
                    $time += 1;
                    $searchImage = str_replace($explodeName[0], (string)$time, $imageWithPath);
                    $searchImageWebp = str_replace($explodeName[0], (string)$time, $imageWebpWithPath);
                    if (file_exists($searchImage)) {
                        rename($searchImage, $imageWithPath);
                    } else {
                        dump($searchImage . " " . 'not exist');
                    }
                    if (file_exists($searchImageWebp)) {
                        rename($searchImageWebp, $imageWebpWithPath);
                    } else {
                        dump($searchImageWebp . " " . 'not exist');
                    }
                }
            }
        }
    }
}
