<?php

/* * *************************************************************
 *  Copyright notice
 *
 *  (c) 2007 Thomas Waggershauser <waggershauser@airware.de>
 *  (c) 2018 Stefan Beyer SEDAT GmbH <stefan@sedat.de>
 *  All rights reserved
 *
 *  This script is part of Cy4Marktzeitung. The Cy4Marktzeitung project is
 *  free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  The GNU General Public License can be found at
 *  http://www.gnu.org/copyleft/gpl.html.
 *
 *  This script is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  This copyright notice MUST APPEAR in all copies of the script!
 * ************************************************************* */
if (!defined('ENTRY_POINT'))
  die('Falscher Aufruf');

/**
 * HTML Cleaner Konfigurieren:
 *
 * Beispiele:
 * HTMLCleaner::allowTag('img', false); erlaubt das img-Tag, entfernt aber alle Attribute
 * HTMLCleaner::allowTag('img', true); erlaubt das img-Tag mit allen Attributen
 * HTMLCleaner::allowTag('img', ['src', 'alt']); erlaubt das img-Tag und die Attribute src und alt
 * HTMLCleaner::allowTag('img', null); Tag ist nicht mehr erlaubt
 */
HTMLCleaner::allowTag('br', false);
#HTMLCleaner::allowTag('i',      false);
#HTMLCleaner::allowTag('em',     false);
#HTMLCleaner::allowTag('b',      false);
#HTMLCleaner::allowTag('strong', false);
HTMLCleaner::allowTag('ol', false);
HTMLCleaner::allowTag('ul', false);
HTMLCleaner::allowTag('li', false);
//HTMLCleaner::allowTag('p',     false);

/**
 * Daten-Extraktor für Custom Fields (callback); siehe _extract_custom_value()
 * TODO besserer Platz dafür
 */
AdsPDF::$extract_custom_value = '_extract_custom_value';

/**
 * Extra-Felder registrieren (Name, Callback)
 */
ExtraFieldManager::register('address', '_extra_field_address');
ExtraFieldManager::register('phone', '_extra_field_phone');
ExtraFieldManager::register('image', '_extra_field_image');
ExtraFieldManager::register('price', '_extra_field_price');

/**
 * Preis
 * @param $ad Inserat-Datensatz, inkl. owner
 * @param $name Name des Feldes (interessant bei Mehrfachverwendung einer Callback)
 * @return string
 */
function _extra_field_price(&$ad, $name) {
  if (property_exists($ad, 'price')) {
    $price = $ad->price;
    $currency = $ad->currency;
    $decimals = property_exists($currency, 'decimalDigits') ? $currency->decimalDigits : 2;
    $prefix = property_exists($currency, 'prefix') ? $currency->prefix : '';
    $suffix = property_exists($currency, 'suffix') ? $currency->suffix : '';
    return $prefix . number_format($price, $decimals, DEC_POINT, THOUSENDS_SEPARATOR) . $suffix;
  } else {
    return 'Ohne Preis';
  }

  return '€€';
}

/**
 * erste Bild als img-Tag
 * @uses IMAGE_WRAPPER_ATTRIBUTES, IMAGE_ATTRIBUTES
 * @param $ad Inserat-Datensatz, inkl. owner
 * @param $name Name des Feldes (interessant bei Mehrfachverwendung einer Callback)
 * @return string
 */
function _extra_field_image(&$ad, $name) {
  if (property_exists($ad, 'image')) {
    $imageURL = $ad->image->url;
    $imageWidth = $ad->image->width;
    $imageHeight = $ad->image->height;
    //$buffer=replaceTemplate($buffer,"imageURL",htmlentities($imageURL));
    $image = '<div ' . IMAGE_WRAPPER_ATTRIBUTES . '><img ' . IMAGE_ATTRIBUTES . ' src="' . htmlentities($imageURL) . '"/></div>';
  } else {
    $image = '';
  }
  return $image;
}

/**
 * erste, nicht versteckte Adresse des Mitglieds ermitteln
 * @param $ad Inserat-Datensatz, inkl. owner
 * @param $name Name des Feldes (interessant bei Mehrfachverwendung einer Callback)
 * @return string
 */
function _extra_field_address(&$ad, $name) {
  if (!$ad->owner || !property_exists($ad->owner, 'addresses'))
    return '';
  if (!is_array($ad->owner->addresses) || empty($ad->owner->addresses))
    return '';
  reset($ad->owner->addresses);
  while (current($ad->owner->addresses) && current($ad->owner->addresses)->hidden) {
    next($ad->owner->addresses);
  }
  $address = current($ad->owner->addresses);
  if (!$address)
    return '';
  //$address = $ad->owner->addresses[0];
  return ($address->street ?? '') . ' ' . ($address->buildingNumber ?? '') . ', ' . ($address->zip ?? '') . ' ' . ($address->city ?? '');
}

/**
 * erste, nicht versteckte Telefonnummer des Mitglieds ermitteln
 * @param $ad Inserat-Datensatz, inkl. owner
 * @param $name Name des Feldes (interessant bei Mehrfachverwendung einer Callback)
 * @return string
 */
function _extra_field_phone(&$ad, $name) {
  if (!$ad->owner || !property_exists($ad->owner, 'phones'))
    return '';
  if (!is_array($ad->owner->phones) || empty($ad->owner->phones))
    return '';
  reset($ad->owner->phones);
  while (current($ad->owner->phones) && current($ad->owner->phones)->hidden) {
    next($ad->owner->phones);
  }
  $phone = current($ad->owner->phones);
  if (!$phone)
    return '';
  return $phone->number;
}

/**
 * Für Custom-Fields: Je nach Typ des Feldes wird
 * die passende Eigenschaft des Objektes herausgesucht.
 * @param $field Custom Field Objekt
 */
function _extract_custom_value($field) {
  switch (strtolower($field->field->type)) {
    case 'string':
    case 'text':
    case 'url':
      return $field->stringValue;
      break;
    case 'singleselection':
      if (isset($field->enumeratedValues[0])) {
        return $field->enumeratedValues[0]->value;
      }
      return null;
      break;
    case 'multipleselection':
    case 'multiselection':
      $values = [];
      foreach ($field->enumeratedValues as &$v) {
        $values[] = $v->value;
      }
      unset($v);
      return implode(' | ', $values);
      //return $values;
      break;
    case 'decimal':
      //return Number2Numberformat(floatval($v->decimalValue), self::getNumberFormat());
      return floatval($field->decimalValue);
      break;
    case 'integer':
      return intval($field->integerValue);
      //return ''.$v->integerValue;
      break;
    case 'boolean':
      // evtl. konfigurieren, wie true und false dargestellt wird
      return $field->booleanValue ? true : false;
      break;
    case 'date':
      return new \DateTime($field->dateValue);
      break;
    default:
      return 'UNBEHANDELTER Feld-Typ: ' . $field->field->type . ' in extract_custom_value()';
  }
}

/**
 * einige defines zusammenfassen (Relikt aus alten Zeiten ;) )
 */
function get_pdf_config() {

  return Array(
      /**
       * y-position where to perform a break (from top of the page)
       */
      "maxY" => PDF_MAX_Y,
      /**
       * category headline
       */
      "category" => Array(
          "disabled" => PDF_CATEGORY_DISABLED, # false (sperren: true)
          "splitChar" => PDF_CATEGORY_SPLITCHAR, # ':' used?
          "main" => Array(
              "fontSize" => PDF_CATEGORY_MAIN_FONTSIZE, # 11
              "height" => PDF_CATEGORY_MAIN_HEIGHT, # 6
              "bgColor" => PDF_CATEGORY_MAIN_BGCOLOR, # 150
              "align" => PDF_CATEGORY_MAIN_ALIGN, # 'C'
              "border" => PDF_CATEGORY_MAIN_BORDER, # 0
          ),
          "sub" => Array(
              "fontSize" => PDF_CATEGORY_SUB_FONTSIZE, # 9
              "height" => PDF_CATEGORY_SUB_HEIGHT, # 5
              "bgColor" => PDF_CATEGORY_SUB_BGCOLOR, # 200
              "align" => PDF_CATEGORY_SUB_ALIGN, # 'L'
              "border" => PDF_CATEGORY_SUB_BORDER, # 0
          ),
          "margin-bottom" => defined('PDF_CATEGORY_MARGIN_BOTTOM') ? PDF_CATEGORY_MARGIN_BOTTOM : 1,
      ),
      /**
       * TradeType headline
       * mit dem Parameter "top" kann eingestellt werden, dass auf jeder Seite
       * Angebote oder Nachfrage ganz oben steht, der Anzeigetyp (tradeType)
       * kann gesperrt werden, damit der Typ in den einzelnen Inseraten nicht mehr
       * angezeigt wird, bei dieser Umstellung ist es aber notwendig, zuerst die
       * Angebote und dann die Nachfragen zu erzeugen (siehe pdf.php)
       *
       */
      "tradeType" => Array(
          "disabled" => PDF_TRADETYPE_DISABLED, # false (sperren: true)
          "fontSize" => PDF_TRADETYPE_FONTSIZE, # 10
          "height" => PDF_TRADETYPE_HEIGHT, # 6
          "border" => PDF_TRADETYPE_BORDER, # 'B'
          "margin-bottom" => PDF_TRADETYPE_MARGIN_BOTTOM, # 2
          "top" => Array(
              "fontSize" => PDF_TRADETYPE_TOP_FONTSIZE, # 12
              "height" => PDF_TRADETYPE_TOP_HEIGHT, # 8
              "align" => PDF_TRADETYPE_TOP_ALIGN, # "C"
              "bgColor" => PDF_TRADETYPE_TOP_BGCOLOR, # #D0D0D0
              "margin-bottom" => PDF_TRADETYPE_TOP_MARGIN_BOTTOM, # 2
          ),
      ),
      /**
       * ad
       * note: margin-bottom ... at the bottom of each ad
       * color_1Week ... #000000 is black (no color)
       * color_2Week ... #000000 is black (no color)
       */
      "ad" => Array(
          "margin-bottom" => PDF_AD_MARGIN_BOTTOM,
          // Zur Zeit nicht unterstützt css verwenden! "border" => PDF_AD_BORDER, # 0 ... keine Linie, 'B' ... Linie bottom
          "color_1Week" => PDF_AD_COLOR_1WEEK, # color for 1-Week ads default: red  #CC0000
          "color_2Week" => PDF_AD_COLOR_2WEEK, # color for 2-Week ads default: blue #0000FF
          "color_1Month" => PDF_AD_COLOR_1MONTH, # color for 1-Week ads default: red  #CC0000
          "color_old" => PDF_AD_COLOR_OLD,
          "fontSize" => PDF_AD_FONTSIZE, # 10
      ),
  );
}

/**
 * Utility function to return a default value when a given one is null
 */
function if_null($value, $default) {
  return is_null($value) ? $default : $value;
}

/**
 * Utility function to ensure an element is returned as array.
 * When null, an empty array. When an array, itself. Otherwise, an array containg the just the element
 */
function ensure_array($element) {
  if (empty($element)) {
    return array();
  }
  if (array_key_exists(0, $element)) {
    return $element;
  }
  return array($element);
}

/**
 * Function replace
 *
 * Anmerkung: Gross-Kleinschreibung wird beruecksichtigt
 *            Gross-Kleinschreibung wird nicht beruecksichtigt (/si)
 *            s - multiline
 *            i - ignore case
 * @param $content ... z.B: html-string
 * @param $search .... searchstring
 * @param $replace ... new text
 * @return replaced content
 */
function replaceAll($content, $search, $replace) {
  $searchpattern = '/' . $search . '/s';
  return preg_replace($searchpattern, $replace, $content);
}

/**
 * Function replaceTemplate
 *
 * Bearbeitung template-item wird nach allen Spaltennamen
 *
 * @param content ... originalwerte
 * @param $key ...... suche nach
 * @param $value .... ersetze mit wert
 *
 * @return replaced template
 */
function replaceTemplate($content, $key, $value) {
  if ($value != '') {
    $result = replaceAll($content, "###" . $key . "###|###{([^}]*?)}" . $key . "{([^}]*?)}###", '${1}' . $value . '${2}');
  } else {
    $result = replaceAll($content, "###" . $key . "###|###{([^}]*?)}" . $key . "{([^}]*?)}###", '');
  }
  return $result;
}

/**
 * Function Color html to rgb
 * @param $color ... #AABBCC
 * @return array(r,g,b)
 */
function html2rgb($color) {
  if ($color[0] == '#') {
    $color = substr($color, 1);
  }
  if (strlen($color) == 6) {
    list($r, $g, $b) = array($color[0] . $color[1],
        $color[2] . $color[3],
        $color[4] . $color[5]);
  } elseif (strlen($color) == 3) {
    list($r, $g, $b) = array($color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2]);
  } else {
    return false;
  }
  $r = hexdec($r);
  $g = hexdec($g);
  $b = hexdec($b);
  return array($r, $g, $b);
}

/**
 * Function Color rgb to html
 * @param $r
 * @param $g
 * @param $b
 * @return #rrggbb
 */
function rgb2html($r, $g = -1, $b = -1) {
  if (is_array($r) && sizeof($r) == 3) {
    list($r, $g, $b) = $r;
  }
  $r = intval($r);
  $g = intval($g);
  $b = intval($b);

  $r = dechex($r < 0 ? 0 : ($r > 255 ? 255 : $r));
  $g = dechex($g < 0 ? 0 : ($g > 255 ? 255 : $g));
  $b = dechex($b < 0 ? 0 : ($b > 255 ? 255 : $b));

  $color = (strlen($r) < 2 ? '0' : '') . $r;
  $color .= (strlen($g) < 2 ? '0' : '') . $g;
  $color .= (strlen($b) < 2 ? '0' : '') . $b;
  return '#' . $color;
}
