<?php
/**
 * @copyright (c) Kufer Software GmbH, Loisachstrasse 4, D-84453 Mühldorf
 */

if (!defined('BASEDIR')) {
  include_once '..' . DIRECTORY_SEPARATOR . 'constants.php';
}


class StatistikAPI
{
  public const STAT_REFERER = 1;
  public const STAT_SUCHANFRAGE = 2;
  public const STAT_KATEGORIE_AUFRUF = 3;
  public const STAT_KURSDETAILS_AUFRUF = 4;
  public const STAT_KURS_IN_WARENKORB = 5;
  public const STAT_KURS_AUS_WARENKORB = 6;
  public const STAT_ANMELDUNG = 7;

  
  public const STAT_FEATURE_ANMELDUNGEN_UND_BESUCHER = 1;
  public const STAT_FEATURE_ANMELDUNGEN_NACH_WOCHENTAG = 2;
  public const STAT_FEATURE_ANMELDUNGEN_NACH_ART = 3;
  public const STAT_FEATURE_ANMELDUNGEN_NACH_STATUS = 4;
  public const STAT_FEATURE_ANMELDUNGEN_NACH_ALTER = 5;
  public const STAT_FEATURE_BELIEBTE_KATEGORIEN = 6;
  public const STAT_FEATURE_BELIEBTE_KURSE = 7;
  public const STAT_FEATURE_KURSSUCHE = 8;
  public const STAT_FEATURE_KURSSUCHE_OHNE_ERGEBNIS = 9;
  public const STAT_FEATURE_GOOGLE_BESUCHER = 10;
  public const STAT_FEATURE_GOOGLE_SUCHBEGRIFFE = 11;


  
  public static $staticDate;

  
  private static function getPreparedEintrag()
  {
    
    $user_id = SessionOperations::getVarValueIntern('stat_user_id', false);
    if ($user_id === false) {
      
      
      
      $user_id = md5(session_id() . time());
      SessionOperations::setVarValueIntern('stat_user_id', $user_id);
    }

    
    $dm = new StatistikEintrag();
    $dm->u_id = $user_id;
    if (isset(StatistikAPI::$staticDate)) {
      $dm->request_date = StatistikAPI::$staticDate;
    } else {
      $dm->request_date = time();
    }
    $dm->user_agent = RequestOperations::getUserAgent();

    return $dm;
  }

  
  private static function isBot($pUserAgent)
  {
    $keywords = array('bot', 'crawl', 'search', 'spider', 'spyder', 'robot', 'scan');
    foreach ($keywords as $keyword) {
      if (StringOperations::stripos($pUserAgent, $keyword) !== false) {
        return true;
      }
    }

    return false;
  }

  
  private static function isWriteStatisticAllowed()
  {
    $settings = AllgSettingsAPI::getAllgSettings();

    return ($settings->statistic_enabled && !StatistikAPI::isBot($_SERVER['HTTP_USER_AGENT']));
  }

  
  private static function write($pAction, $pParams)
  {
    
    $dm = StatistikAPI::getPreparedEintrag();

    $dm->request_action = $pAction;
    $dm->params = $pParams;

    $dbw = new DBWorkStatistik();
    if ($dbw->dboperation->checkConnection()) {
      $dbw->createEintrag($dm);
    }
  }

  
  public static function writeReferer($pReferer)
  {
    if (! StatistikAPI::isWriteStatisticAllowed()) {
      return;
    }

    $servername = strip_tags($_SERVER['SERVER_NAME']);

    
    if (!StringOperations::startsWith($pReferer, 'http://' . $servername) && !StringOperations::startsWith($pReferer, 'https://' . $servername)) {
      $params = array();
      $i = 1;
      do {
        $params[] = new StatistikParameter('referer_part' . $i++, StringOperations::substr($pReferer, 0, 255));
        $pReferer = StringOperations::substr($pReferer, 255);
      } while (StringOperations::strlen($pReferer) > 0);

      StatistikAPI::write(self::STAT_REFERER, $params);
    }
  }

  public static function writeKursdetailsAufruf($pParam)
  {
    if (StatistikAPI::isWriteStatisticAllowed()) {
      StatistikAPI::write(self::STAT_KURSDETAILS_AUFRUF, array($pParam));
    }
  }

  
  public static function writeKursdetailsAufrufOnlyDiff($pParam)
  {
    if (! StatistikAPI::isWriteStatisticAllowed()) {
      return;
    }

    $request_action = self::STAT_KURSDETAILS_AUFRUF;

    
    if (!StatistikAPI::checkIfEintragExistInSession($request_action, $pParam)) {
      StatistikAPI::write($request_action, array($pParam));
      StatistikAPI::setEintragInSession($request_action, $pParam);
    }
  }

  public static function writeKategorieAufruf($pParam)
  {
    if (StatistikAPI::isWriteStatisticAllowed()) {
      StatistikAPI::write(self::STAT_KATEGORIE_AUFRUF, array($pParam));
    }
  }

  
  public static function writeKategorieAufrufOnlyDiff($pParam)
  {
    if (!StatistikAPI::isWriteStatisticAllowed()) {
      return;
    }

    $request_action = self::STAT_KATEGORIE_AUFRUF;

    
    if (!StatistikAPI::checkIfEintragExistInSession($request_action, $pParam)) {
      StatistikAPI::write($request_action, array($pParam));
      StatistikAPI::setEintragInSession($request_action, $pParam);
    }
  }

  
  public static function writeSuchanfrage($pParams)
  {
    if (StatistikAPI::isWriteStatisticAllowed()) {
      StatistikAPI::write(self::STAT_SUCHANFRAGE, $pParams);
    }
  }

  
  public static function writeKursInWarenkorb($pParam)
  {
    if (StatistikAPI::isWriteStatisticAllowed()) {
      StatistikAPI::write(self::STAT_KURS_IN_WARENKORB, array($pParam));
    }
  }

  
  public static function writeKursAusWarenkorb($pParam)
  {
    if (StatistikAPI::isWriteStatisticAllowed()) {
      StatistikAPI::write(self::STAT_KURS_AUS_WARENKORB, array($pParam));
    }
  }

  
  public static function writeAnmeldung($pParams)
  {
    if (StatistikAPI::isWriteStatisticAllowed()) {
      StatistikAPI::write(self::STAT_ANMELDUNG, $pParams);
    }
  }

  public static function getParamsSuchanfrage($pCountKurse)
  {
    $params = array();
    $params[] = new StatistikParameter('treffer', $pCountKurse);
    foreach ($_SESSION as $key => $value) {
      $insert = true;
      $prefix = SESSION_PREFIX . SESSION_PREFIX_INTERN . SESSION_PREFIX_SUCHE . 'kfs_';

      
      $insert = $insert && StringOperations::strpos($key, $prefix) !== false;
      if (is_array($value)) {
        $insert = false;
      } else {
        $insert = $insert && trim($value) != '';
      }

      
      $key = str_replace($prefix, '', $key);
      switch ($key) {
        case 'suchegesetzt':
          $insert = false;
          break;
        case 'kursbereich':
        case 'sonderrubrik':
          $insert = $insert && $value > 0;
          break;
      }

      
      if ($insert) {
        $params[] = new StatistikParameter($key, $value);
      }
    }

    return $params;
  }

  
  public static function aggregiereStatistiken()
  {
    StatistikAPI::_aggregateStatistikAnmeldungenUndBesucher();
    StatistikAPI::_aggregateStatistikBeliebteKategorien();
    StatistikAPI::_aggregateStatistikBeliebteKurse();
    StatistikAPI::_aggregateStatistikKursSuche();
    StatistikAPI::_aggregateStatistikGoogle();
  }

  
  private static function monateDiff($monthYearArray1, $monthYearArray2)
  {
    foreach ($monthYearArray1 as $allKey => $monthYear1) {
      foreach ($monthYearArray2 as $monthYear2) {
        if ($monthYear1['month'] == $monthYear2['month']
        && $monthYear1['year'] == $monthYear2['year']) {
          unset($monthYearArray1[$allKey]);
          break;
        }
      }
    }

    return $monthYearArray1;
  }

  
  private static function _aggregateStatistikAnmeldungenUndBesucher()
  {
    
    $dbStatistik = new DBWorkStatistik(1, true);

    
    $monthYearArray = StatistikAPI::_getMonthAggregationNecessary(self::STAT_ANMELDUNG);

    
    
    
    $monthYearArrayAll = StatistikAPI::_getMonthAggregationNecessary4AllRequestActions();
    
    $monthYearArrayDiff = StatistikAPI::monateDiff($monthYearArrayAll, $monthYearArray);

    foreach ($monthYearArrayDiff as $monthYearDiff) {
      $dateDiff = '01.'
        . ((StringOperations::strlen($monthYearDiff['month']) == 1) ? '0' : '') . $monthYearDiff['month'] . '.'
        . $monthYearDiff['year'];
      
      $aggrStatistiken = $dbStatistik->getAggregatByFeatureAndDate($dateDiff, $dateDiff, self::STAT_FEATURE_ANMELDUNGEN_UND_BESUCHER);
      if (empty($aggrStatistiken)) {
        $monthYearArray[] = $monthYearDiff;
      }
    }

    
    foreach ($monthYearArray as $monthYear) {
      
      $date = '01.'
        . ((StringOperations::strlen($monthYear['month']) == 1) ? '0' : '') . $monthYear['month'] . '.'
        . $monthYear['year'];

      
      $dbStatistik->deleteAggregatedStatisticByDateAndFeature($date, $date, self::STAT_FEATURE_ANMELDUNGEN_UND_BESUCHER);
      $dbStatistik->deleteAggregatedStatisticByDateAndFeature($date, $date, self::STAT_FEATURE_ANMELDUNGEN_NACH_WOCHENTAG);
      $dbStatistik->deleteAggregatedStatisticByDateAndFeature($date, $date, self::STAT_FEATURE_ANMELDUNGEN_NACH_ART);
      $dbStatistik->deleteAggregatedStatisticByDateAndFeature($date, $date, self::STAT_FEATURE_ANMELDUNGEN_NACH_STATUS);
      $dbStatistik->deleteAggregatedStatisticByDateAndFeature($date, $date, self::STAT_FEATURE_ANMELDUNGEN_NACH_ALTER);

      
      $visits = $dbStatistik->getStatCountVisits($date, $date);

      $bookings = $dbStatistik->getStatCountBookings($date, $date);

      $statTemp = new StatistikAggregation();
      $statTemp->monat = $monthYear['month'];
      $statTemp->jahr = $monthYear['year'];
      $statTemp->feature = self::STAT_FEATURE_ANMELDUNGEN_UND_BESUCHER;
      $statTemp->anzahl = $visits;
      $statTemp->subfeature = $bookings;
      $statTemp->sonstiges = ($bookings == 0 ? 0 : round($bookings / $visits, 2));

      $dbStatistik->createAggregate($statTemp);

      
      $bpw = $dbStatistik->getStatBookingsPerWeekday($date, $date);
      foreach ($bpw as $wochentag => $anzahl) {
        $statTemp = new StatistikAggregation();
        $statTemp->monat = $monthYear['month'];
        $statTemp->jahr = $monthYear['year'];
        $statTemp->feature = self::STAT_FEATURE_ANMELDUNGEN_NACH_WOCHENTAG;
        $statTemp->anzahl = $anzahl;
        $statTemp->subfeature = $wochentag;

        $dbStatistik->createAggregate($statTemp);
      }

      
      $anmStat = $dbStatistik->getStatAnmWithStatus($date, $date);
      foreach ($anmStat as $status => $anzahl) {
        $statTemp = new StatistikAggregation();
        $statTemp->monat = $monthYear['month'];
        $statTemp->jahr = $monthYear['year'];
        $statTemp->feature = self::STAT_FEATURE_ANMELDUNGEN_NACH_STATUS;
        $statTemp->anzahl = $anzahl;
        $statTemp->subfeature = $status;

        $dbStatistik->createAggregate($statTemp);
      }

      
      $anmArt = $dbStatistik->getStatAnmWithArtByDate($date, $date);
      foreach ($anmArt as $art => $anzahl) {
        $statTemp = new StatistikAggregation();
        $statTemp->monat = $monthYear['month'];
        $statTemp->jahr = $monthYear['year'];
        $statTemp->feature = self::STAT_FEATURE_ANMELDUNGEN_NACH_ART;
        $statTemp->anzahl = $anzahl;
        $statTemp->subfeature = $art;

        $dbStatistik->createAggregate($statTemp);
      }

      
      $anmAge = $dbStatistik->getStatBookingsPerAge($date, $date);
      foreach ($anmAge as $alter => $anzahl) {
        $statTemp = new StatistikAggregation();
        $statTemp->monat = $monthYear['month'];
        $statTemp->jahr = $monthYear['year'];
        $statTemp->feature = self::STAT_FEATURE_ANMELDUNGEN_NACH_ALTER;
        $statTemp->anzahl = $anzahl;
        $statTemp->subfeature = $alter;

        $dbStatistik->createAggregate($statTemp);
      }

      
      $dbStatistik->deleteStatisticByDateAndRequestAction($date, $date, self::STAT_ANMELDUNG);
    }
  }

  
  private static function _aggregateStatistikBeliebteKategorien()
  {
    
    $monthYearArray = StatistikAPI::_getMonthAggregationNecessary(self::STAT_KATEGORIE_AUFRUF);
    $dbStatistik = new DBWorkStatistik(1, true);

    
    foreach ($monthYearArray as $monthYear) {
      
      $date = '01.'
        . ((StringOperations::strlen($monthYear['month']) == 1) ? '0' : '') . $monthYear['month'] . '.'
        . $monthYear['year'];

      
      $dbStatistik->deleteAggregatedStatisticByDateAndFeature($date, $date, self::STAT_FEATURE_BELIEBTE_KATEGORIEN);

      
      $kurseStatAry = $dbStatistik->getStatCategories($date, $date);
      foreach ($kurseStatAry as $katID => $kurseStat) {
        $statTemp = new StatistikAggregation();
        $statTemp->monat = $monthYear['month'];
        $statTemp->jahr = $monthYear['year'];
        $statTemp->feature = self::STAT_FEATURE_BELIEBTE_KATEGORIEN;
        $statTemp->anzahl = $kurseStat['count'];
        $statTemp->subfeature = $katID;
        $statTemp->sonstiges = $kurseStat['title'];

        $dbStatistik->createAggregate($statTemp);
      }

      
      $dbStatistik->deleteStatisticByDateAndRequestAction($date, $date, self::STAT_KATEGORIE_AUFRUF);
    }
  }

  
  private static function _aggregateStatistikBeliebteKurse()
  {
    
    
    $monthYearArray = StatistikAPI::_getMonthAggregationNecessary(array(self::STAT_KURSDETAILS_AUFRUF, self::STAT_KURS_IN_WARENKORB, self::STAT_KURS_AUS_WARENKORB));
    $dbStatistik = new DBWorkStatistik(1, true);

    
    foreach ($monthYearArray as $monthYear) {
      
      $date = '01.'
        . ((StringOperations::strlen($monthYear['month']) == 1) ? '0' : '') . $monthYear['month'] . '.'
        . $monthYear['year'];

      
      $dbStatistik->deleteAggregatedStatisticByDateAndFeature($date, $date, self::STAT_FEATURE_BELIEBTE_KURSE);

      
      $kurseStatAry = $dbStatistik->getStatKurse($date, $date);
      foreach ($kurseStatAry as $kurseStat) {
        $statTemp = new StatistikAggregation();
        $statTemp->monat = $monthYear['month'];
        $statTemp->jahr = $monthYear['year'];
        $statTemp->feature = self::STAT_FEATURE_BELIEBTE_KURSE;
        $statTemp->anzahl = $kurseStat['count'];
        $statTemp->subfeature = $kurseStat['kursnr'];
        $statTemp->sonstiges = $kurseStat['title'];

        $dbStatistik->createAggregate($statTemp);
      }

      
      $dbStatistik->deleteStatisticByDateAndRequestAction($date, $date, self::STAT_KURSDETAILS_AUFRUF);
      $dbStatistik->deleteStatisticByDateAndRequestAction($date, $date, self::STAT_KURS_IN_WARENKORB);
      
      $dbStatistik->deleteStatisticByDateAndRequestAction($date, $date, self::STAT_KURS_AUS_WARENKORB);
    }
  }

  
  private static function _aggregateStatistikKursSuche()
  {
    
    $monthYearArray = StatistikAPI::_getMonthAggregationNecessary(self::STAT_SUCHANFRAGE);
    $dbStatistik = new DBWorkStatistik(1, true);

    
    foreach ($monthYearArray as $monthYear) {
      
      $date = '01.'
        . ((StringOperations::strlen($monthYear['month']) == 1) ? '0' : '') . $monthYear['month'] . '.'
        . $monthYear['year'];

      
      $dbStatistik->deleteAggregatedStatisticByDateAndFeature($date, $date, self::STAT_FEATURE_KURSSUCHE);
      $dbStatistik->deleteAggregatedStatisticByDateAndFeature($date, $date, self::STAT_FEATURE_KURSSUCHE_OHNE_ERGEBNIS);

      
      $wordsAry = $dbStatistik->getStatSearchwords($date, $date);
      foreach ($wordsAry as $begriff => $anzahl) {
        $statTemp = new StatistikAggregation();
        $statTemp->monat = $monthYear['month'];
        $statTemp->jahr = $monthYear['year'];
        $statTemp->feature = self::STAT_FEATURE_KURSSUCHE;
        $statTemp->anzahl = $anzahl;
        $statTemp->subfeature = $begriff;

        $dbStatistik->createAggregate($statTemp);
      }

      
      $wordsAry = $dbStatistik->getStatStichwortSearchWithoutHit($date, $date);
      foreach ($wordsAry as $begriff => $anzahl) {
        $statTemp = new StatistikAggregation();
        $statTemp->monat = $monthYear['month'];
        $statTemp->jahr = $monthYear['year'];
        $statTemp->feature = self::STAT_FEATURE_KURSSUCHE_OHNE_ERGEBNIS;
        $statTemp->anzahl = $anzahl;
        $statTemp->subfeature = $begriff;

        $dbStatistik->createAggregate($statTemp);
      }
      
      $dbStatistik->deleteStatisticByDateAndRequestAction($date, $date, self::STAT_SUCHANFRAGE);
    }
  }

  
  private static function _aggregateStatistikGoogle()
  {
    
    $monthYearArray = StatistikAPI::_getMonthAggregationNecessary(self::STAT_REFERER);
    $dbStatistik = new DBWorkStatistik(1, true);

    
    foreach ($monthYearArray as $monthYear) {
      
      $date = '01.'
        . ((StringOperations::strlen($monthYear['month']) == 1) ? '0' : '') . $monthYear['month'] . '.'
        . $monthYear['year'];

      
      $dbStatistik->deleteAggregatedStatisticByDateAndFeature($date, $date, self::STAT_FEATURE_GOOGLE_BESUCHER);
      $dbStatistik->deleteAggregatedStatisticByDateAndFeature($date, $date, self::STAT_FEATURE_GOOGLE_SUCHBEGRIFFE);

      
      $visits = $dbStatistik->getStatCountGoogleVisits($date, $date);
      $statTemp = new StatistikAggregation();
      $statTemp->monat = $monthYear['month'];
      $statTemp->jahr = $monthYear['year'];
      $statTemp->feature = self::STAT_FEATURE_GOOGLE_BESUCHER;
      $statTemp->anzahl = $visits;

      $dbStatistik->createAggregate($statTemp);

      
      $searchExpr = $dbStatistik->getStatGoogleSearchExpr($date, $date);
      foreach ($searchExpr as $exp => $exp_value) {
        $statTemp = new StatistikAggregation();
        $statTemp->monat = $monthYear['month'];
        $statTemp->jahr = $monthYear['year'];
        $statTemp->feature = self::STAT_FEATURE_GOOGLE_SUCHBEGRIFFE;
        $statTemp->anzahl = $exp_value['count'];
        $statTemp->subfeature = $exp;
        $statTemp->sonstiges = $exp_value['ranking'];

        $dbStatistik->createAggregate($statTemp);
      }
      
      $dbStatistik->deleteStatisticByDateAndRequestAction($date, $date, self::STAT_REFERER);
    }
  }

  
  private static function _getMonthAggregationNecessary($pRequestAction)
  {
    
    $dbStatistik = new DBWorkStatistik(1, true);
    $requestActionAry = (is_array($pRequestAction)) ? $pRequestAction : array($pRequestAction);
    $date = $dbStatistik->getDateOfOldestByRequestAction($requestActionAry);
    $dateNow = DateTimeOperations::getDateNow();
    $monat = (int)StringOperations::substr($date, 3, 2);
    $jahr = (int)StringOperations::substr($date, 6, 4);
    $monatNow = (int)StringOperations::substr($dateNow, 3, 2);
    $jahrNow = (int)StringOperations::substr($dateNow, 6, 4);

    
    
    $result = array();
    $countMonate = ($jahrNow - $jahr) * 12 + ($monatNow - $monat);
    for ($i = 0; $i < $countMonate; $i++) {
      $tempMonat = ($monat - 1 + $i) % 12 + 1;
      $tempJahr = $jahr + (int)(($monat - 1 + $i) / 12);
      $result[] = array('month' => $tempMonat, 'year' => $tempJahr);
    }

    return $result;
  }

  
  private static function _getMonthAggregationNecessary4AllRequestActions()
  {
    
    

    return StatistikAPI::_getMonthAggregationNecessary(array(
              self::STAT_REFERER,
              self::STAT_SUCHANFRAGE,
              self::STAT_KATEGORIE_AUFRUF,
              self::STAT_KURSDETAILS_AUFRUF,
              self::STAT_KURS_IN_WARENKORB,
              self::STAT_KURS_AUS_WARENKORB,
              self::STAT_ANMELDUNG
            ));
  }

  
  private static function checkIfEintragExistInSession($pRequestAction, $pParam)
  {
    return SessionOperations::isDefinedIntern($pParam->param_name . '_' . $pParam->param_value . '_' . $pRequestAction);
  }

  private static function setEintragInSession($pRequestAction, $pParam)
  {
    $dummyValue = 1;
    SessionOperations::setVarValueIntern($pParam->param_name . '_' . $pParam->param_value . '_' . $pRequestAction, $dummyValue);
  }
}