<?php
class formsControllerCfs extends controllerCfs
{
  private $_prevFormId = 0;
  private $_forceModelName = '';

  public function createFromTpl()
  {
    $res = new responseCfs();
    if (($id = $this->getModel()->createFromTpl(reqCfs::get('post'))) != false) {
      $res->addMessage(__('Done', CFS_LANG_CODE));
      $res->addData('edit_link', $this->getModule()->getEditLink($id));
    } else {
      $res->pushError($this->getModel()->getErrors());
    }
    return $res->ajaxExec();
  }
  protected function _prepareListForTblContacts($data)
  {
    if (!empty($data)) {
      $fieldsHtml = reqCfs::getVar('contact_fields_to_html');
      foreach ($data as $i => $v) {
        $viewLinkSet = false;
        if (!empty($data[$i]['fields']) && !is_array($data[$i]['fields'])) {
          $data[$i]['fields'] = unserialize(base64_decode($data[$i]['fields']));
        }
        if (isset($data[$i]['fields']) && !empty($data[$i]['fields'])) {
          foreach ($data[$i]['fields'] as $fK => $fV) {
            $fieldVal = $fV;
            if (!empty($fieldVal) && is_array($fieldVal)) {
              $fieldVal = implode(', ', $fieldVal);
            }
            if (!empty($fieldVal) && !$viewLinkSet) {
              $data[$i]['user_field_' . $fK] = '<a href="' . $data[$i]['id'] . '" class="cfsFormContactPrevLnk">' . $fieldVal . '&nbsp;<i class="fa fa-search"></i></a>';
              $viewLinkSet = true;
            } else {
              $html = !empty($fieldsHtml) && isset($fieldsHtml[$fK]) ? $fieldsHtml[$fK] : false;
              switch ($html) {
                case 'file':
                  if (frameCfs::_()->getModule('add_fields')) {
                    $idPubHash = explode('|', $fieldVal);
                    $id = is_numeric($idPubHash[0]) ? (int) $idPubHash[0] : false;
                    if ($id) {
                      global $wpdb;
                      $file = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}cfs_files WHERE id = %s", $id), ARRAY_A);
                      if (!empty($file)) {
                        $data[$i]['user_field_' . $fK] = '<a href="' . frameCfs::_()->getModule('add_fields')->getFileUrl($file) . '"><i class="fa fa-cloud-download"></i>&nbsp;' . __('Download', CFS_LANG_CODE) . '</a>';
                      }
                    }
                  }
                  break;
                default:
                  $data[$i]['user_field_' . $fK] = $fieldVal;
                  break;
              }
            }
          }
          unset($data[$i]['fields']);
        }
      }
    }
    return $data;
  }
  protected function _prepareListForTbl($data)
  {
    if (!empty($data)) {
      if ($this->_forceModelName == 'contacts') {
        $fieldsHtml = reqCfs::getVar('contact_fields_to_html');
        foreach ($data as $i => $v) {
          $viewLinkSet = false;
          if (isset($data[$i]['fields']) && !empty($data[$i]['fields'])) {
            foreach ($data[$i]['fields'] as $fK => $fV) {
              $fieldVal = $fV;
              if (!empty($fieldVal) && is_array($fieldVal)) {
                $fieldVal = implode(', ', $fieldVal);
              }
              if (!empty($fieldVal) && !$viewLinkSet) {
                $data[$i]['user_field_' . $fK] = '<a href="' . $data[$i]['id'] . '" class="cfsFormContactPrevLnk">' . $fieldVal . '&nbsp;<i class="fa fa-search"></i></a>';
                $viewLinkSet = true;
              } else {
                $html = !empty($fieldsHtml) && isset($fieldsHtml[$fK]) ? $fieldsHtml[$fK] : false;
                switch ($html) {
                  case 'file':
                    if (frameCfs::_()->getModule('add_fields')) {
                      $idPubHash = explode('|', $fieldVal);
                      $id = is_numeric($idPubHash[0]) ? (int) $idPubHash[0] : false;
                      if ($id) {
                        $file = frameCfs::_()
                          ->getTable('files')
                          ->get('*', ['id' => $id], '', 'row');
                        if (!empty($file)) {
                          $data[$i]['user_field_' . $fK] = '<a href="' . frameCfs::_()->getModule('add_fields')->getFileUrl($file) . '"><i class="fa fa-cloud-download"></i>&nbsp;' . __('Download', CFS_LANG_CODE) . '</a>';
                        }
                      }
                    }
                    break;
                  default:
                    $data[$i]['user_field_' . $fK] = $fieldVal;
                    break;
                }
              }
            }
            unset($data[$i]['fields']);
          }
        }
      } else {
        foreach ($data as $i => $v) {
          $data[$i]['label'] = '<a class="" href="' . $this->getModule()->getEditLink($data[$i]['id']) . '">' . esc_html($data[$i]['label']) . '&nbsp;<i class="fa fa-fw fa-pencil" style="margin-top: 2px;"></i></a>';
          $conversion = 0;
          if (!empty($data[$i]['unique_views']) && !empty($data[$i]['actions'])) {
            $conversion = number_format((int) $data[$i]['actions'] / (int) $data[$i]['unique_views'], 3);
          }
          $data[$i]['conversion'] = $conversion;
          $data[$i]['active'] = $data[$i]['active'] ? '<span class="alert alert-success">' . __('Yes', CFS_LANG_CODE) . '</span>' : '<span class="alert alert-danger">' . __('No', CFS_LANG_CODE) . '</span>';
        }
      }
    }
    return $data;
  }
  // protected function _prepareTextLikeSearch($val) {
  // 	if($this->_forceModelName == 'contacts') {
  // 		$query = '(ip LIKE "%'. $val. '%" OR url LIKE "%'. $val. '%"';
  // 	} else {
  // 		$query = '(label LIKE "%'. $val. '%"';
  // 	}
  // 	if(is_numeric($val)) {
  // 		$query .= ' OR id LIKE "%'. (int) $val. '%"';
  // 	}
  // 	$query .= ')';
  // 	return $query;
  // }
  // protected function _prepareModelBeforeListSelect($model) {
  // 	if($this->_forceModelName == 'contacts') {
  //
  // 	} else {
  // 		$where = 'original_id != 0';
  // 		$abTestCondAdded = false;
  // 		if(frameCfs::_()->getModule('ab_testing')) {
  // 			$abBaseId = frameCfs::_()->getModule('ab_testing')->getListForBaseId();
  // 			if(!empty($abBaseId)) {
  // 				$where .= ' AND ab_id = '. $abBaseId;
  // 				$abTestCondAdded = true;
  // 			}
  // 		}
  // 		if(!$abTestCondAdded) {
  // 			$where .= ' AND ab_id = 0';
  // 		}
  // 		$model->addWhere( $where );
  // 		dispatcherCfs::doAction('formsModelBeforeGetList', $model);
  // 	}
  // 	return $model;
  // }
  // protected function _prepareSortOrder($sortOrder) {
  // 	if($sortOrder == 'conversion') {
  // 		$sortOrder = '(actions / unique_views)';	// Conversion in real-time calculation
  // 	}
  // 	return $sortOrder;
  // }
  public function remove()
  {
    $res = new responseCfs();
    if ($this->getModel()->remove(reqCfs::getVar('id', 'post'))) {
      $res->addMessage(__('Done', CFS_LANG_CODE));
    } else {
      $res->pushError($this->getModel()->getErrors());
    }
    $res->ajaxExec();
  }
  public function save()
  {
    $res = new responseCfs();
    if ($this->getModel()->save(reqCfs::get('post'))) {
      $res->addMessage(__('Done', CFS_LANG_CODE));
    } else {
      $res->pushError($this->getModel()->getErrors());
    }
    $res->ajaxExec();
  }
  public function getPreviewHtml()
  {
    $this->_prevFormId = (int) reqCfs::getVar('id', 'get');
    $this->outPreviewHtml();
    //add_action('init', array($this, 'outPreviewHtml'));
  }
  public function outPreviewHtml()
  {
    if ($this->_prevFormId) {
      $form = $this->getModel()->supGetById($this->_prevFormId);
      $formContent = $this->getView()->generateHtml($form);
      echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
			<html dir="' .
        (function_exists('is_rtl') && is_rtl() ? 'rtl' : 'ltr') .
        '"><head>' .
        '<meta content="' .
        get_option('html_type') .
        '; charset=' .
        get_option('blog_charset') .
        '" http-equiv="Content-Type">' .
        $this->_generateRecaptchaAssetsForPrev($form) .
        $this->getModule()->getAssetsforPrevStr($form) .
        '<style type="text/css">
				html { overflow: visible !important; }
				.cfsFormShell {
					display: block;
					position: static;
				}
				</style>' .
        '</head>';
      echo '<body id="cfsFormPreviewBody">';
      echo $formContent;
      echo '<body></html>';
    }
    exit();
  }
  private function _generateRecaptchaAssetsForPrev($form)
  {
    // check if there are recaptcha field in fields list
    if (!empty($form['params']['fields'])) {
      foreach ($form['params']['fields'] as $f) {
        if ($f['html'] == 'recaptcha') {
          return '<script src="https://www.google.com/recaptcha/api.js" async defer></script>';
        }
      }
    }
    return '';
  }
  public function changeTpl()
  {
    $res = new responseCfs();
    if ($this->getModel()->changeTpl(reqCfs::get('post'))) {
      $res->addMessage(__('Done', CFS_LANG_CODE));
      $id = (int) reqCfs::getVar('id', 'post');
      // Redirect after change template - to Design tab, as change tpl btn is located there - so, user was at this tab before changing tpl
      $res->addData('edit_link', $this->getModule()->getEditLink($id, 'cfsFormTpl'));
    } else {
      $res->pushError($this->getModel()->getErrors());
    }
    return $res->ajaxExec();
  }
  public function exportForDb()
  {
    $eol = "\r\n";

    $forPro = (int) reqCfs::getVar('for_pro', 'get');
    $tblsCols = [
      '@__forms' => ['unique_id', 'label', 'active', 'original_id', 'params', 'html', 'css', 'sort_order', 'date_created', 'is_pro', 'img_preview'],
    ];
    if ($forPro) {
      echo 'db_install=>';
      foreach ($tblsCols as $tbl => $cols) {
        echo $this->_makeExportQueriesLogicForPro($tbl, $cols);
      }
    } else {
      foreach ($tblsCols as $tbl => $cols) {
        echo "if(function_exists('base64_encode')) {" . $eol;
        echo $this->_makeExportQueriesLogic($tbl, $cols);
        echo '} else {	//--not-base64--' . $eol;
        echo $this->_makeExportQueriesLogic($tbl, $cols, true);
        echo '}';
      }
    }
    exit();
  }
  private function _makeExportQueriesLogicForPro($table, $cols)
  {
    global $wpdb;
    $octoList = $this->_getExportData($table, $cols, true);
    $res = [];

    foreach ($octoList as $octo) {
      $uId = '';
      $rowData = [];
      foreach ($octo as $k => $v) {
        if (!in_array($k, $cols)) {
          continue;
        }
        $val = $wpdb->_real_escape($v);
        if ($k == 'unique_id') {
          $uId = $val;
        }
        $rowData[$k] = $val;
      }
      $res[$uId] = $rowData;
    }
    echo str_replace(['@__'], '', $table) . '|' . base64_encode(utilsCfs::serialize($res));
  }
  private function _getExportData($table, $cols, $forPro = false)
  {
    return dbCfs::get('SELECT ' . implode(',', $cols) . ' FROM ' . $table . ' WHERE original_id = 0 and is_pro = ' . ($forPro ? '1' : '0'));
  }
  /**
   * new usage
   */
  private function _makeExportQueriesLogic($table, $cols, $forceOrd = false)
  {
    global $wpdb;
    $eol = "\r\n";
    $tab = "\t";
    $octoList = $this->_getExportData($table, $cols);
    $valuesArr = [];
    $allKeys = [];
    $uidIndx = 0;
    $i = 0;
    foreach ($octoList as $octo) {
      $arr = [];
      $addToKeys = empty($allKeys);
      $i = 0;
      foreach ($octo as $k => $v) {
        $value = $v;
        if (!in_array($k, $cols)) {
          continue;
        }
        if ($addToKeys) {
          $allKeys[] = $k;
          if ($k == 'unique_id') {
            $uidIndx = $i;
          }
        }
        if ($k == 'params' && $forceOrd) {
          $value = utilsCfs::encodeArrayTxt(utilsCfs::decodeArrayTxt($value), true);
        }
        $arr[] = '' . $wpdb->_real_escape($value) . '';
        $i++;
      }
      $valuesArr[] = $arr;
    }
    $out = '';
    //$out .= "\$cols = array('". implode("','", $allKeys). "');". $eol;
    $out .= "\$data = array(" . $eol;
    foreach ($valuesArr as $row) {
      $uid = str_replace(['"'], '', $row[$uidIndx]);
      $installData = [];
      foreach ($row as $i => $v) {
        $installData[] = "'{$allKeys[$i]}' => '{$v}'";
      }
      $out .= $tab . "'$uid' => array(" . implode(',', $installData) . '),' . $eol;
    }
    $out .= ');' . $eol;
    return $out;
  }
  public function saveAsCopy()
  {
    $res = new responseCfs();
    if (($id = $this->getModel()->saveAsCopy(reqCfs::get('post'))) != false) {
      $res->addMessage(__('Done, redirecting to new Form...', CFS_LANG_CODE));
      $res->addData('edit_link', $this->getModule()->getEditLink($id));
    } else {
      $res->pushError($this->getModel()->getErrors());
    }
    return $res->ajaxExec();
  }
  public function switchActive()
  {
    $res = new responseCfs();
    if ($this->getModel()->switchActive(reqCfs::get('post'))) {
      $res->addMessage(__('Done', CFS_LANG_CODE));
    } else {
      $res->pushError($this->getModel()->getErrors());
    }
    return $res->ajaxExec();
  }
  public function updateLabel()
  {
    $res = new responseCfs();
    if ($this->getModel()->updateLabel(reqCfs::get('post'))) {
      $res->addMessage(__('Done', CFS_LANG_CODE));
    } else {
      $res->pushError($this->getModel()->getErrors());
    }
    return $res->ajaxExec();
  }
  public function updateNonce()
  {
    $res = new responseCfs();
    $getFor = reqCfs::getVar('get_for', 'post');
    $id = (int) reqCfs::getVar('id', 'post');
    $updateFor = [];
    if (!empty($getFor) && !empty($id)) {
      $generateKeys = [
        'cfsContactForm' => 'contact-' . $id,
      ];
      foreach ($getFor as $gf) {
        if (isset($generateKeys[$gf])) {
          $updateFor[$gf] = wp_create_nonce($generateKeys[$gf]);
        }
      }
    }
    if (!empty($updateFor)) {
      $res->addData('update_for', $updateFor);
    }
    return $res->ajaxExec();
  }
  public function contact()
  {
    $res = new responseCfs();
    $data = reqCfs::get('post');
    $id = isset($data['id']) ? (int) $data['id'] : 0;
    $nonce = isset($_REQUEST['_wpnonce']) ? $_REQUEST['_wpnonce'] : reqCfs::getVar('_wpnonce');
    if (!wp_verify_nonce($nonce, 'contact-' . $id)) {
      die('Some error with your request.........');
    }
    // Add some statistics
    frameCfs::_()
      ->getModule('statistics')
      ->getModel()
      ->add(['id' => $id, 'type' => 'submit']);

    if ($this->getModel()->contact($data)) {
      $lastForm = $this->getModel()->getLastForm();
      $successMsg = isset($lastForm['params']['tpl']['form_sent_msg']) ? $lastForm['params']['tpl']['form_sent_msg'] : __('Thank you for contacting us!', CFS_LANG_CODE);
      $successMsg = dispatcherCfs::applyFilters('contactSuccessMsg', $successMsg, $lastForm);
      $res->addMessage($successMsg);
      $redirectUrl = isset($lastForm['params']['tpl']['redirect_on_submit']) && !empty($lastForm['params']['tpl']['redirect_on_submit']) ? $lastForm['params']['tpl']['redirect_on_submit'] : false;
      $redirectUrl = dispatcherCfs::applyFilters('contactSuccessRedirectUrl', $redirectUrl, $lastForm);
      if (!empty($redirectUrl)) {
        if (isset($lastForm['params']['tpl']['redirect_to_submitted']) && $lastForm['params']['tpl']['redirect_to_submitted']) {
          $lastSavedContactId = $this->getModel()->getLastSavedContactId();
          $redirectUrl = uriCfs::_([
            'baseUrl' => $redirectUrl,
            'fid' => $lastForm['id'],
            'cid' => $lastSavedContactId,
            'hash' => md5(AUTH_KEY . $lastForm['id'] . $lastSavedContactId),
          ]);
        }
        $res->addData('redirect', uriCfs::normal($redirectUrl));
      }
    } else {
      $res->pushError($this->getModel()->getErrors());
    }
    frameCfs::_()
      ->getModule('statistics')
      ->getModel()
      ->add([
        'id' => $id,
        'type' => $res->error() ? 'submit_error' : 'submit_success',
      ]);
    return $res->ajaxExec();
  }
  public function exportCsv()
  {
    $id = (int) reqCfs::getVar('id');
    $delim = trim(reqCfs::getVar('delim'));
    $form = $this->getModel()->supGetById($id);

    importClassCfs('filegeneratorCfs');
    importClassCfs('csvgeneratorCfs');

    $fileTitle = sprintf(__('Contacts from %s', CFS_LANG_CODE), htmlspecialchars($form['label']));
    $csvGenerator = new csvgeneratorCfs($fileTitle);
    if (!empty($delim)) {
      $csvGenerator->setDelimiter($delim);
    }
    $labels = [];
    // Add additional subscribe fields
    if (isset($form['params']['fields']) && !empty($form['params']['fields'])) {
      foreach ($form['params']['fields'] as $f) {
        $labels['user_field_' . $f['name']] = $f['label'];
      }
    }
    $labels = array_merge($labels, [
      'ip' => __('IP', CFS_LANG_CODE),
      'url' => __('URL', CFS_LANG_CODE),
      'form_id' => __('Form ID', CFS_LANG_CODE),
      'date_created' => __('Date Created', CFS_LANG_CODE),
    ]);
    $contacts = $this->getModel()->getContactsForForm($id);

    $row = $cell = 0;
    foreach ($labels as $l) {
      $csvGenerator->addCell($row, $cell, $l);
      $cell++;
    }
    $row = 1;
    if (!empty($contacts)) {
      foreach ($contacts as $c) {
        $cell = 0;
        foreach ($labels as $k => $l) {
          $getKey = $k;
          if (strpos($getKey, 'user_field_') === 0) {
            $getKey = str_replace('user_field_', '', $getKey);
            $value = isset($c['fields'][$getKey]) ? $c['fields'][$getKey] : '';
          } else {
            $value = $c[$getKey];
          }
          if (is_array($value)) {
            $value = implode(', ', $value);
          }
          $csvGenerator->addCell($row, $cell, $value);
          $cell++;
        }
        $row++;
      }
    } else {
      $cell = 0;
      $noUsersMsg = __('There are no Contacts for now', CFS_LANG_CODE);
      $csvGenerator->addCell($row, $cell, $noUsersMsg);
    }
    $csvGenerator->generate();
  }
  public function getContactsListForTbl()
  {
    $res = new responseCfs();
    $res->ignoreShellData();
    $model = $this->getModel();
    $page = (int) sanitize_text_field(reqCfs::getVar('page'));
    $rowsLimit = (int) sanitize_text_field(reqCfs::getVar('rows'));
    $search = reqCfs::getVar('search');
    $formId = !empty($search['form_id']) ? sanitize_text_field($search['form_id']) : '';
    $search = !empty($search['text_like']) ? sanitize_text_field($search['text_like']) : '';

    // Get total pages count for current request
    $totalCount = $model->getContactsTotalCountBySearch($search);
    $totalPages = 0;
    if ($totalCount > 0) {
      $totalPages = ceil($totalCount / $rowsLimit);
    }
    if ($page > $totalPages) {
      $page = $totalPages;
    }
    // Calc limits - to get data only for current set
    $limitStart = $rowsLimit * $page - $rowsLimit; // do not put $limit*($page - 1)
    if ($limitStart < 0) {
      $limitStart = 0;
    }

    $data = $model->getContactsListForTblBySearch($search, $limitStart, $rowsLimit, $formId);

    $data = $this->_prepareListForTblContacts($data);
    $res->addData('page', $page);
    $res->addData('total', $totalPages);
    $res->addData('rows', $data);
    $res->addData('records', $model->getLastGetCount());
    $res = dispatcherCfs::applyFilters($this->getCode() . '_getListForTblResults', $res);
    $res->ajaxExec();
  }
  public function getListForTbl()
  {
    $res = new responseCfs();
    $res->ignoreShellData();
    $model = $this->getModel();
    $page = (int) sanitize_text_field(reqCfs::getVar('page'));
    $rowsLimit = (int) sanitize_text_field(reqCfs::getVar('rows'));
    $search = reqCfs::getVar('search');
    $search = !empty($search['text_like']) ? sanitize_text_field($search['text_like']) : '';

    // Get total pages count for current request
    $totalCount = $model->getTotalCountBySearch($search);
    $totalPages = 0;
    if ($totalCount > 0) {
      $totalPages = ceil($totalCount / $rowsLimit);
    }
    if ($page > $totalPages) {
      $page = $totalPages;
    }
    // Calc limits - to get data only for current set
    $limitStart = $rowsLimit * $page - $rowsLimit; // do not put $limit*($page - 1)
    if ($limitStart < 0) {
      $limitStart = 0;
    }

    $data = $model->getListForTblBySearch($search, $limitStart, $rowsLimit);

    $data = $this->_prepareListForTbl($data);

    $res->addData('page', $page);
    $res->addData('total', $totalPages);
    $res->addData('rows', $data);
    $res->addData('records', $model->getLastGetCount());
    $res = dispatcherCfs::applyFilters($this->getCode() . '_getListForTblResults', $res);
    $res->ajaxExec();
  }
  public function getModel($name = '')
  {
    if (empty($name) && !empty($this->_forceModelName)) {
      $name = $this->_forceModelName;
    }
    return parent::getModel($name);
  }
  public function getContactDetails()
  {
    $res = new responseCfs();
    if (($contact = $this->getModel('contacts')->supGetById(reqCfs::getVar('id'))) != false) {
      $res->addData('contact', $contact);
      $form = $this->getModel()->supGetById($contact['form_id']);
      if ($form && $form['params']['fields']) {
        $res->addData('form_fields', $form['params']['fields']);
      }
      $res->addData('form_label', $form['label']);
    } else {
      $res->pushError($this->getModel('contacts')->getErrors());
    }
    return $res->ajaxExec();
  }
  public function removeContactsGroup()
  {
    $this->_forceModelName = 'contacts';
    return parent::removeGroup();
  }
  public function getNoncedMethods()
  {
    return ['save', 'removeGroup', 'getListForTbl', 'saveAsCopy', 'remove', 'createFromTpl', 'changeTpl'];
  }
  public function getPermissions()
  {
    return [
      CFS_USERLEVELS => [
        CFS_ADMIN => ['createFromTpl', 'getListForTbl', 'remove', 'removeGroup', 'clear', 'save', 'getPreviewHtml', 'exportForDb', 'changeTpl', 'saveAsCopy', 'switchActive', 'outPreviewHtml', 'updateLabel', 'exportCsv', 'getContactsListForTbl', 'getContactDetails', 'removeContactsGroup'],
      ],
    ];
  }
}
