<?php

class gmapViewGmp extends viewGmp
{
  //private $_gmapApiUrl = "https://maps.googleapis.com/maps/api/js?&sensor=false&=";
  private $_gmapApiUrl = '';
  private static $_mapsData;
  private $_mapsObj = [];
  private $_shortCodeHtmlParams = ['width', 'height', 'align'];
  private $_paramsCanNotBeEmpty = ['width', 'height'];
  private $_mapStyles = [];
  private $_displayColumns = [];
  // Used to compare rand IDs and original IDs on preview

  public function getApiUrl()
  {
    if (empty($this->_gmapApiUrl)) {
      $apiDomain = $this->getApiDomain();
      $urlParams = dispatcherGmp::applyFilters('gApiUrlParams', ['key' => $this->getApiKey()]);
      $this->_gmapApiUrl = $apiDomain . 'maps/api/js?' . http_build_query($urlParams);
    }
    return $this->_gmapApiUrl;
  }
  public function getApiDomain()
  {
    $apiDomain = 'https://maps.googleapis.com/';

    if ($chosenApiDomain = frameGmp::_()->getModule('options')->get('api_domain')) {
      $apiDomain = $chosenApiDomain;
    }
    return $apiDomain;
  }
  public function getApiKey()
  {
    $apiKey = '';

    if ($userApiKey = dispatcherGmp::applyFilters('gRewriteApiKey', frameGmp::_()->getModule('options')->get('user_api_key'))) {
      $apiKey = trim($userApiKey);
    }
    return $apiKey;
  }
  public function addMapData($params)
  {
    if (empty(self::$_mapsData)) {
      self::$_mapsData = [];
    }
    if (!empty($params)) {
      self::$_mapsData[] = $params;
    }
  }
  public function getMapData()
  {
    return self::$_mapsData;
  }
  public function getMapsObj()
  {
    if (empty($this->_mapsObj)) {
      $mapsInPosts = $this->getModule()->getMapsInPosts();

      foreach ($mapsInPosts as $mapId) {
        $mapObj = frameGmp::_()->getModule('gmap')->getModel()->getMapById($mapId);

        if (empty($mapObj)) {
          continue;
        }

        $mapObj['isDisplayed'] = false;
        $this->_mapsObj[$mapObj['view_id']] = $mapObj;
      }
    }
    return $this->_mapsObj;
  }
  public function addMapStyles($mapViewId)
  {
    $mapObj = is_array($mapViewId) ? $mapViewId : $this->_mapsObj[$mapViewId];
    $mapsInPostsParams = $this->getModule()->_mapsInPostsParams;

    if (!empty($mapsInPostsParams) && !empty($mapsInPostsParams[$mapObj['view_id']])) {
      $mapObj = $this->applyShortcodeHtmlParams($mapObj, $mapsInPostsParams[$mapObj['view_id']]);
      $mapObj = $this->applyShortcodeMapParams($mapObj, $mapsInPostsParams[$mapObj['view_id']]);
    }
    $this->prepareMapHtmlParams($mapObj);
    $this->assign('currentMap', $mapObj);
    array_push($this->_mapStyles, $mapObj['view_id']);

    return parent::getContent('gmapMapStyles');
  }
  public function drawMap($params)
  {
    $mapObj = [];
    $mapMarkersGroupsList = [];

    foreach ($this->_mapsObj as $view_id => $map) {
      if ($map['id'] == $params['id'] && !$map['isDisplayed']) {
        $this->_mapsObj[$view_id]['isDisplayed'] = true;
        $mapObj = $this->_mapsObj[$view_id];
        break;
      }
    }

    $byUserId = false;
    if (isset($params['user_id']) && !empty($params['user_id'])) {
      switch ($params['user_id']) {
        case 'logged_in_user':
          $byUserId = get_current_user_id();
          $byUserId = $byUserId == 0 ? false : $byUserId;
          break;
        default:
          $byUserId = (int) $params['user_id'];
          break;
      }
    }

    $mapObj = $mapObj ? $mapObj : frameGmp::_()->getModule('gmap')->getModel()->getMapById($params['id'], true, false, true, true, $byUserId);

    if (empty($mapObj)) {
      return isset($params['id']) ? sprintf(__('Map with ID %d not found', GMP_LANG_CODE), $params['id']) : __('Map not found', GMP_LANG_CODE);
    }
    $mapObj = $this->applyShortcodeHtmlParams($mapObj, $params);
    $mapObj = $this->applyShortcodeMapParams($mapObj, $params);

    if (!empty($mapObj['markers'])) {
      if (!empty($params['marker_show_description'])) {
        foreach ($mapObj['markers'] as $key => $marker) {
          if (isset($marker['params']['show_description'])) {
            unset($mapObj['markers'][$key]['params']['show_description']);
          }
          if ($marker['id'] == $params['marker_show_description']) {
            $mapObj['markers'][$key]['params']['show_description'] = 1;
          }
        }
      }

      if ($byUserId) {
        foreach ($mapObj['markers'] as $key => &$marker) {
          if (!is_null($marker['user_id']) && (int) $marker['user_id'] != $byUserId) {
            unset($mapObj['markers'][$key]);
          }
        }
        $mapObj['markers'] = array_values($mapObj['markers']);
      }

      if (!empty($params['marker_category'])) {
        $category = explode(',', $params['marker_category']);
        foreach ($mapObj['markers'] as $key => $marker) {
          if (count(array_intersect($marker['marker_group_ids'], $category)) > 0) {
            continue;
          }
          unset($mapObj['markers'][$key]);
        }
        $mapObj['markers'] = array_values($mapObj['markers']); // 'reindex' array
      }
    }
    if (isset($params['display_as_img']) && $params['display_as_img']) {
      $mapObj['params']['map_display_mode'] = 'popup';
      $mapObj['params']['img_width'] = isset($params['img_width']) ? $params['img_width'] : 175;
      $mapObj['params']['img_height'] = isset($params['img_height']) ? $params['img_height'] : 175;
    }
    if (isset($params['display_as_img']) && $params['display_as_img']) {
      $mapObj['params']['map_display_mode'] = 'popup';
    }
    if ($mapObj['params']['map_display_mode'] == 'popup') {
      frameGmp::_()->addScript('jquery-ui-dialog', '', ['jquery']);
      frameGmp::_()->getModule('templates')->loadJqueryUi();
      frameGmp::_()->addStyle('supsystic-uiGmp', GMP_CSS_PATH . 'supsystic-ui.css');
      frameGmp::_()->getModule('templates')->loadFontAwesome();
    }
    if (empty($mapObj['params']['map_display_mode'])) {
      $mapObj['params']['map_display_mode'] = 'map';
    }
    if ($mapMarkersGroupsList) {
      $mapObj['marker_groups'] = frameGmp::_()->getModule('marker_groups')->getModel()->getMarkerGroupsByIds($mapMarkersGroupsList);
    }
    $mapVarTemp = isset($mapObj['params']['markers_list_type']) && !empty($mapObj['params']['markers_list_type']) ? $mapObj['params']['markers_list_type'] : '';
    $mapObj['params']['markers_list_type'] = isset($params['markers_list_type']) ? $params['markers_list_type'] : $mapVarTemp;

    $mapObj = dispatcherGmp::applyFilters('mapDataRender', $mapObj);
    // for Social Share integration
    $mapObj['params']['ss_html'] = $this->generateSocialSharingHtml($mapObj);
    $isPro = frameGmp::_()->getModule('supsystic_promo')->isPro();
    if ($isPro) {
      $routeData = frameGmp::_()->getModule('heatmap')->getModel()->getRouteByMapId($params['id']);
      if (!empty($routeData['json'])) {
        frameGmp::_()->addJSVar('frontend.router.js', 'gmpRouterJson', $routeData['json']);
        $mapObj['routes'] = 1;
      }
    }
    // Connect map assets
    $this->connectMapsAssets($mapObj['params']);
    frameGmp::_()->addScript('frontend.gmap', $this->getModule()->getModPath() . 'js/frontend.gmap.js', ['jquery'], false, true);
    // Add styles if they were not added yet
    $content = '';
    if (!in_array($mapObj['view_id'], $this->_mapStyles)) {
      $content .= $this->addMapStyles($mapObj);
    }
    $mapObj['params']['html_options'] = $this->htmlOptions; // have created in $this->addMapStyles function
    // Add map object to js
    $this->addMapData(dispatcherGmp::applyFilters('mapDataToJs', $mapObj));

    $this->assign('markersDisplayType', $mapObj['params']['markers_list_type']);
    $this->assign('currentMap', $mapObj);

    if ($isPro) {
      frameGmp::_()->addScript('gmap.path.decoder', frameGmp::_()->getModule('heatmap')->getModPath() . 'js/path.decoder.js');
      frameGmp::_()->addScript('frontend.router.js', frameGmp::_()->getModule('heatmap')->getModPath() . 'js/frontend.router.js');
      $apiKey = frameGmp::_()->getModule('options')->get('user_api_key');
      frameGmp::_()->addJSVar('frontend.router.js', 'gmpApiKey', $apiKey);
      $routeData = frameGmp::_()->getModule('heatmap')->getModel()->getRouteByMapId($params['id']);
      if (!empty($routeData['json'])) {
        frameGmp::_()->addJSVar('frontend.router.js', 'gmpRouterJson', $routeData['json']);
      }
      $this->assign('routeData', $routeData);
    }

    return $content . parent::getInlineContent('gmapDrawMap');
  }
  public function prepareMapHtmlParams($mapObj)
  {
    $htmlOptions = $mapObj['html_options'];
    $htmlOptions['width_units'] = isset($mapObj['params']['width_units']) ? $mapObj['params']['width_units'] : 'px';
    $htmlOptions['width'] = $htmlOptions['width_units'] === '%' && (int) $htmlOptions['width'] > 100 ? 100 : trim($htmlOptions['width']);
    if ($mapObj['params']['map_display_mode'] === 'popup') {
      $htmlOptions['width_units'] = '%';
      $htmlOptions['width'] = 100;
    }
    $htmlOptions['width_full'] = (int) $htmlOptions['width'] . $htmlOptions['width_units'];
    $htmlOptions['height'] = trim($mapObj['html_options']['height']);
    $htmlOptions['height_units'] = 'px';
    $htmlOptions['height_full'] = $htmlOptions['height'] . $htmlOptions['height_units'];
    if (!empty($htmlOptions['align'])) {
      $htmlOptions['align'] = trim($htmlOptions['align']);
    }
    if (!empty($htmlOptions['border_width']) && !empty($htmlOptions['border_color'])) {
      $htmlOptions['border_color'] = trim($htmlOptions['border_width']) . 'px solid ' . trim($htmlOptions['border_color']);
    }
    if (!empty($htmlOptions['margin'])) {
      $htmlOptions['margin'] = trim($htmlOptions['margin']) . 'px';
    }
    $this->assign('htmlOptions', $htmlOptions);

    return $mapObj;
  }
  public function applyShortcodeHtmlParams($mapObj, $params)
  {
    foreach ($this->_shortCodeHtmlParams as $code) {
      if (isset($params[$code])) {
        if (in_array($code, $this->_paramsCanNotBeEmpty) && empty($params[$code])) {
          continue;
        }
        $mapObj['html_options'][$code] = $params[$code];
      }
    }
    return $mapObj;
  }
  public function applyShortcodeMapParams($mapObj, $params)
  {
    $shortCodeMapParams = $this->getModel()->getParamsList();

    if (isset($params['map_center']) && is_string($params['map_center'])) {
      if (strpos($params['map_center'], ';')) {
        $centerXY = array_map('trim', explode(';', $params['map_center']));
        $params['map_center'] = [
          'coord_x' => $centerXY[0],
          'coord_y' => $centerXY[1],
        ];
      } elseif (is_numeric($params['map_center'])) {
        // Map center - is coords of one of it's marker
        $params['map_center'] = (int) trim($params['map_center']);
        $found = false;

        if (!empty($mapObj['markers'])) {
          foreach ($mapObj['markers'] as $marker) {
            if ($marker['id'] == $params['map_center']) {
              $params['map_center'] = [
                'coord_x' => $marker['coord_x'],
                'coord_y' => $marker['coord_y'],
              ];
              $found = true;
              break;
            }
          }
        }
        // If no marker with such ID were found - just unset it to prevent map broke
        if (!$found) {
          unset($params['map_center']);
        }
      } else {
        // If it is set, but not valid - just unset it to not break user map
        unset($params['map_center']);
      }
    }
    foreach ($shortCodeMapParams as $code) {
      if (isset($params[$code])) {
        if (in_array($code, $this->_paramsCanNotBeEmpty) && empty($params[$code])) {
          continue;
        }
        $mapObj['params'][$code] = $params[$code];
      }
    }
    return $mapObj;
  }
  public function addMapDataToJs()
  {
    frameGmp::_()->addJSVar('frontend.gmap', 'gmpAllMapsInfo', self::$_mapsData);
  }
  public function getDisplayColumns()
  {
    if (empty($this->_displayColumns)) {
      $this->_displayColumns = [
        'id' => ['label' => __('ID'), 'db' => 'id'],
        'title' => ['label' => __('Title'), 'db' => 'title'],
        'list_html_options' => ['label' => __('Html options'), 'db' => 'html_options'],
        'list_markers' => ['label' => __('Markers'), 'db' => 'markers'],
        'operations' => ['label' => __('Operations'), 'db' => 'operations'],
      ];
    }
    return $this->_displayColumns;
  }
  public function getListMarkers($map)
  {
    $this->assign('map', $map);
    return parent::getContent('gmapListMarkers');
  }
  public function getListOperations($map)
  {
    $this->assign('map', $map);
    $this->assign('editLink', $this->getModule()->getEditMapLink($map['id']));
    return parent::getContent('gmapListOperations');
  }
  public function getTabContent()
  {
    frameGmp::_()->getModule('templates')->loadJqGrid();
    frameGmp::_()->addScript('admin.gmap', $this->getModule()->getModPath() . 'js/admin.gmap.js');
    frameGmp::_()->addScript('admin.gmap.list', $this->getModule()->getModPath() . 'js/admin.gmap.list.js');
    frameGmp::_()->addJSVar('admin.gmap.list', 'gmpTblDataUrl', uriGmp::mod('gmap', 'getListForTbl', ['reqType' => 'ajax']));
    frameGmp::_()->addStyle('admin.gmap', $this->getModule()->getModPath() . 'css/admin.gmap.css');

    $this->assign('addNewLink', frameGmp::_()->getModule('options')->getTabUrl('gmap_add_new'));
    return parent::getContent('gmapAdmin');
  }
  public function getEditMap($id = 0)
  {
    $editMap = $id ? true : false;
    $isPro = frameGmp::_()->getModule('supsystic_promo')->isPro();
    $gMapApiParams = ['language' => ''];
    $markerLists = $this->getModule()->getMarkerLists();
    $positionsList = $this->getModule()->getControlsPositions();
    $isContactFormsInstalled = utilsGmp::classExists('frameCfs');
    $customControlsUnit = $this->getModule()->getCustomControlsUnit();

    $allStylizationsList = $this->getModule()->getStylizationsList();
    $stylizationsForSelect = ['none' => __('None', GMP_LANG_CODE)];

    foreach ($allStylizationsList as $styleName => $json) {
      $stylizationsForSelect[$styleName] = $styleName; // JSON data will be attached on js side
    }
    frameGmp::_()->getModule('templates')->loadJqGrid();
    frameGmp::_()->addScript('jquery-ui-sortable');
    frameGmp::_()->addScript('wp.tabs', GMP_JS_PATH . 'wp.tabs.js');
    frameGmp::_()->addScript('admin.gmap', $this->getModule()->getModPath() . 'js/admin.gmap.js');
    frameGmp::_()->addScript('admin.gmap.edit', $this->getModule()->getModPath() . 'js/admin.gmap.edit.js');
    frameGmp::_()->addScript('admin.marker.edit', frameGmp::_()->getModule('marker')->getModPath() . 'js/admin.marker.edit.js');

    frameGmp::_()->addStyle('admin.gmap', $this->getModule()->getModPath() . 'css/admin.gmap.css');

    frameGmp::_()->addJSVar('admin.gmap.edit', 'gmpMapShortcode', GMP_SHORTCODE);
    frameGmp::_()->addJSVar('admin.gmap.edit', 'gmpAllStylizationsList', $allStylizationsList);
    frameGmp::_()->addJSVar('admin.gmap.edit', 'gmpMapsListUrl', frameGmp::_()->getModule('options')->getTabUrl('gmap'));

    // jqGrid tables urls
    $gmpMarkersTblDataUrl = uriGmp::mod('marker', 'getListForTbl', ['reqType' => 'ajax', 'map_id' => $id]);
    frameGmp::_()->addJSVar('admin.gmap.edit', 'gmpMarkersTblDataUrl', $gmpMarkersTblDataUrl);
    frameGmp::_()->addJSVar('admin.marker.edit', 'gmpMarkersTblDataUrl', $gmpMarkersTblDataUrl);

    if ($isPro) {
      $gmpShapesTblDataUrl = uriGmp::mod('shape', 'getListForTbl', ['reqType' => 'ajax', 'map_id' => $id]);
      frameGmp::_()->addJSVar('admin.gmap.edit', 'gmpShapesTblDataUrl', $gmpShapesTblDataUrl);
      frameGmp::_()->addJSVar('admin.shape.edit', 'gmpShapesTblDataUrl', $gmpShapesTblDataUrl);
    }
    if ($editMap) {
      $map = $this->getModel()->getMapById($id);
      $gMapApiParams = $map['params'];
      $mapMarkersGroupsList = [];
      $mapMarkersGroups = [];

      if ($map['markers'] && !empty($map['markers'])) {
        foreach ($map['markers'] as $marker) {
          if ($marker['marker_group_id']) {
            if (in_array($marker['marker_group_id'], $mapMarkersGroupsList)) {
              continue;
            }
            array_push($mapMarkersGroupsList, $marker['marker_group_id']);
          }
        }
      }
      if ($mapMarkersGroupsList) {
        $allMarkerGroupsList = frameGmp::_()->getModule('marker_groups')->getModel()->getAllMarkerGroups();

        foreach ($allMarkerGroupsList as $group) {
          if (in_array($group['id'], $mapMarkersGroupsList)) {
            array_push($mapMarkersGroups, $group);
          }
        }
        $map['marker_groups'] = $mapMarkersGroups;
      }

      $this->assign('map', $map);

      frameGmp::_()->addJSVar('admin.gmap.edit', 'gmpMainMap', $map);

      if ($isPro) {
        frameGmp::_()->addScript('gmap.path.decoder', frameGmp::_()->getModule('heatmap')->getModPath() . 'js/path.decoder.js');
        frameGmp::_()->addScript('admin.router.js', frameGmp::_()->getModule('heatmap')->getModPath() . 'js/admin.router.js');
        $apiKey = frameGmp::_()->getModule('options')->get('user_api_key');
        frameGmp::_()->addJSVar('admin.router.js', 'gmpApiKey', $apiKey);
        $routeData = frameGmp::_()->getModule('heatmap')->getModel()->getRouteByMapId($id);
        if (!empty($routeData['json'])) {
          frameGmp::_()->addJSVar('admin.router.js', 'gmpRouterJson', $routeData['json']);
        }
        $this->assign('routeData', $routeData);
      }
    }

    $this->connectMapsAssets($gMapApiParams, true);

    $this->assign('editMap', $editMap);
    $this->assign('isPro', $isPro);
    $this->assign(
      'icons',
      frameGmp::_()
        ->getModule('icons')
        ->getModel()
        ->getIcons(['fields' => 'id, path, title']),
    );
    $this->assign('countries', $this->getModule()->getCountriesList());
    $this->assign('stylizationsForSelect', $stylizationsForSelect);
    $this->assign('positionsList', $positionsList);
    $this->assign('customControlsUnit', $customControlsUnit);
    $this->assign('mainLink', frameGmp::_()->getModule('supsystic_promo')->getMainLink());
    $this->assign('markerLists', $markerLists);
    $this->assign(
      'markerGroupsForSelect',
      frameGmp::_()
        ->getModule('marker_groups')
        ->getModel()
        ->getMarkerGroupsForSelect(['0' => __('None', GMP_LANG_CODE)]),
    );
    $this->assign('viewId', $editMap ? $map['view_id'] : 'preview_id_' . mt_rand(1, 9999));
    $this->assign('promoModPath', frameGmp::_()->getModule('supsystic_promo')->getModPath());

    if ($isContactFormsInstalled) {
      frameGmp::_()->addJSVar('admin.gmap.edit', 'gmpContactFormEditUrl', frameCfs::_()->getModule('options')->getTabUrl('forms_edit'));
      $this->assign('contactFormsForSelect', $this->getAllContactForms());
    }
    $this->assign('isContactFormsInstalled', $isContactFormsInstalled);

    return parent::getContent('gmapEditMap');
  }
  public function getAllContactForms()
  {
    $formsList = [];
    global $wpdb;
    $forms = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}cfs_forms WHERE original_id != 0 AND ab_id = 0", ARRAY_A);
    if ($forms) {
      foreach ($forms as $f) {
        $formsList[$f['id']] = $f['label'];
      }
    }
    return $formsList;
  }

  public function connectMapsAssets($params, $forAdminArea = false)
  {
    if (!$forAdminArea && isset($params['is_static']) && (int) $params['is_static']) {
      // Maybe we will need some additional assets in future, for now - it's light as lighting :)
      if (frameGmp::_()->getModule('supsystic_promo')->isPro() && frameGmp::_()->getModule('add_map_options') && method_exists(frameGmp::_()->getModule('add_map_options'), 'connectStaticMapCore')) {
        frameGmp::_()->getModule('add_map_options')->connectStaticMapCore();
      }
    } else {
      $params['language'] = isset($params['language']) && !empty($params['language']) ? $params['language'] : utilsGmp::getLangCode2Letter();

      frameGmp::_()->addScript('google_maps_api', $this->getApiUrl() . '&language=' . $params['language']);
      frameGmp::_()->addScript('core.gmap', $this->getModule()->getModPath() . 'js/core.gmap.js');
      frameGmp::_()->addScript('core.marker', frameGmp::_()->getModule('marker')->getModPath() . 'js/core.marker.js');
      if ((isset($params['marker_clasterer']) && $params['marker_clasterer'] != 'none') || $forAdminArea) {
        //frameGmp::_()->addScript('core.markerclusterer', $this->getModule()->getModPath(). 'js/core.markerclusterer.min.js');
        frameGmp::_()->addScript('core.markerclusterer', $this->getModule()->getModPath() . 'js/core.markerclusterer.js', [], '1.0');
      }

      frameGmp::_()->addStyle('core.gmap', $this->getModule()->getModPath() . 'css/core.gmap.css');

      dispatcherGmp::doAction('afterConnectMapAssets', $params, $forAdminArea);
    }
  }

  public function generateSocialSharingHtml($map)
  {
    $res = '';
    $socialSharingHtml = apply_filters('supsystic_gmap_sm_html', '', $map);

    if (!empty($socialSharingHtml)) {
      $res = $socialSharingHtml;
    }

    return $res;
  }
}