<?php


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

class StringObj
{
  protected $string;

  
  public function __construct($pString = null)
  {
    $this->string = $this->getPHPString($pString);
  }

  
  protected function getPHPString($pString)
  {
    $string = '';
    if ($pString !== null) {
      $type = gettype($pString);
      
      
      
      
      
      
      
      
      

      if ($type == 'object') {
        if (get_class($pString) == get_class($this)) {
          $string = $pString->toString();
        } else {
          throw new InvalidArgumentExceptionExtended('$pString', $pString, 'Der Parameter muss wenn er ein Objekt ist vom Typ String sein.');
        }
      } elseif ($type == 'array') {
        throw new InvalidArgumentExceptionExtended('$pString', $pString, 'Der Parameter muss darf kein Array sein.');
      } elseif ($type == 'resource') {
        throw new InvalidArgumentExceptionExtended('$pString', $pString, 'Der Parameter muss darf keine Resource sein.');
      } elseif ($type == 'unknown type') {
        throw new InvalidArgumentExceptionExtended('$pString', $pString, 'Der Parameter muss darf nicht vom Typ Unknown Type sein.');
      } else { 
        $pString = (string)$pString;
        $string = $pString;
      }
    }

    return $string;
  }

  
  public function toString()
  {
    return $this->string;
  }

  
  public function add($pString)
  {
    $this->string = $this->string . $this->getPHPString($pString);

    return $this;
  }

  
  public function addLine($pString)
  {
    $this->string = $this->string . "\n" . $this->getPHPString($pString);

    return $this;
  }

  
  public function startsWith($pString, $pCase = true)
  {
    $string = $this->getPHPString($pString);

    return \StringOperations::startsWith($this->string, $string, $pCase);
  }

  
  public function endsWith($pString, $pCaseSensitive = true)
  {
    $string = $this->getPHPString($pString);
    $expectedPosition = StringOperations::strlen($this->string) - StringOperations::strlen($string);
    if ($pCaseSensitive) {
      return strrpos($this->string, $string, 0) === $expectedPosition;
    }

    return strripos($this->string, $string, 0) === $expectedPosition;
  }

  
  public function contains($pString, $pCase = true)
  {
    $string = $this->getPHPString($pString);
    if ($pCase) {
      return strrpos($this->string, $string, 0) !== false;
    }

    return strripos($this->string, $string, 0) !== false;
  }

  
  public function containsAny($pStrings, $pCase = true)
  {
    $return = false;
    if (is_array($pStrings)) {
      foreach ($pStrings as $string) {
        if ($this->contains($string, $pCase)) {
          $return = true;
          break;
        }
      }
    }

    return $return;
  }

  
  public function removeLastChars($pCount)
  {
    $tmp = '';
    if ($this->length() > $pCount) {
      $tmp = StringOperations::substr($this->string, 0, -$pCount);
    }

    return new StringObj($tmp);
  }

  
  public function removeFirstChars($pCount)
  {
    $tmp = '';
    if ($this->length() > $pCount) {
      $tmp = StringOperations::substr($this->string, $pCount);
    }

    return new StringObj($tmp);
  }

  
  public function length()
  {
    return StringOperations::strlen($this->string);
  }

  
  public function __equals($object)
  {
    return $this->string == $object->string;
  }

  
  public function __toString()
  {
    return $this->string;
  }

  
  public function replace($pPattern, $pReplacement, $pCase = true, $pCount = false)
  {
    $pattern = $this->getPHPString($pPattern);
    $replacement = $this->getPHPString($pReplacement);
    $tmp = '';
    if ($pCase) {
      if ($pCount === false) {
        $tmp = str_replace($pattern, $replacement, $this->string);
      } else {
        $tmp = str_replace($pattern, $replacement, $this->string, $pCount);
      }
    } elseif ($pCount === false) {
      $tmp = \StringOperations::str_ireplace($pattern, $replacement, $this->string);
    } else {
      $tmp = \StringOperations::str_ireplace($pattern, $replacement, $this->string, $pCount);
    }

    return new StringObj($tmp);
  }

  
  public function replaceAny($pToFindAndReplaceMapping, $pCase = true)
  {
    $tempStr = clone $this;
    if (is_array($pToFindAndReplaceMapping)) {
      foreach ($pToFindAndReplaceMapping as $key => $value) {
        $tempStr = $tempStr->replace($key, $value, $pCase);
      }
    }

    return $tempStr;
  }

  
  public function replaceRegex($pPattern, $pReplacement, $pLimit = -1)
  {
    $pattern = $this->getPHPString($pPattern);
    $replacement = $this->getPHPString($pReplacement);

    $tmp = preg_replace($pattern, $replacement, $this->string, $pLimit);

    if ($tmp === null) {
      $errorCode = preg_last_error();
      if ($errorCode != PREG_NO_ERROR) {
        $text = $this->errorCodeToText($errorCode);

        throw new Exception(StringOperations::utf8_encode("Die Ersetzung konnte nicht durchgeführt werden.\r\n\r\nErrorcode: " . $errorCode . "\r\nError: " . $text));
      }
    }

    return new StringObj($tmp);
  }

  protected function errorCodeToText($errcode)
  {
    static $errtext;

    if (!isset($errtext)) {
      $errtext = array();
      $constants = get_defined_constants(true);
      foreach ($constants['pcre'] as $c => $n) {
        if (preg_match('/_ERROR$/', $c)) {
          $errtext[$n] = $c;
        }
      }
    }

    return array_key_exists($errcode, $errtext) ? $errtext[$errcode] : null;
  }

  
  public function copy()
  {
    return new StringObj($this->string);
  }

  
  public function __clone()
  {
    return $this->copy();
  }

  
  public function trim($pCharlistToTrim = null)
  {
    $charlist = $this->getPHPString($pCharlistToTrim);
    $tmp = '';
    if ($charlist != null) {
      $tmp = trim($this->string, $charlist);
    } else {
      $tmp = trim($this->string);
    }

    return new StringObj($tmp);
  }

  
  public function trimStart($pCharlistToTrim = null)
  {
    $charlist = $this->getPHPString($pCharlistToTrim);
    $tmp = '';
    if ($charlist != null) {
      $tmp = ltrim($this->string, $charlist);
    } else {
      $tmp = ltrim($this->string);
    }

    return new StringObj($tmp);
  }

  
  public function trimEnd($pCharlistToTrim = null)
  {
    $charlist = $this->getPHPString($pCharlistToTrim);
    $tmp = '';
    if ($charlist != null) {
      $tmp = rtrim($this->string, $charlist);
    } else {
      $tmp = rtrim($this->string);
    }

    return new StringObj($tmp);
  }

  
  public function isEmpty()
  {
    return $this->string === null || $this->string === '';
  }

  
  public function Clear()
  {
    $this->string = '';
  }

  
  public function subString($pOffset, $pLength = null)
  {
    if ($pLength == null) {
      return new StringObj(StringOperations::substr($this->string, $pOffset));
    } else {
      return new StringObj(StringOperations::substr($this->string, $pOffset, $pLength));
    }
  }

  
  public function split($pDelimiter, $pLimit)
  {
    $delimiter = $this->getPHPString($pDelimiter);
    $array = explode($delimiter, $this->string, $pLimit);
    $tmp = array();
    foreach ($array as $str) {
      $tmp[] = new StringObj($str);
    }

    return $tmp;
  }

  
  public function splitMulti($pDelimiters)
  {
    $delimiters = array();
    foreach ($pDelimiters as $delimiter) {
      $delimiters[] = $this->getPHPString($delimiter);
    }
    $ready = str_replace($delimiters, $delimiters[0], $this->string);
    $launch = explode($delimiters[0], $ready);

    $tmp = array();
    foreach ($launch as $str) {
      $tmp[] = new StringObj($str);
    }

    return $tmp;
  }

  
  public function toUpperCase()
  {
    return new StringObj(StringOperations::strtoupper($this->string));
  }

  
  public function toLowerCase()
  {
    return new StringObj(StringOperations::strtolower($this->string));
  }

  
  public function reverse()
  {
    return new StringObj(strrev($this->string));
  }

  
  public function pad($pLength, $pPadString = ' ')
  {
    $padstring = $this->getPHPString($pPadString);

    return new StringObj(\StringOperations::pad($this->string, $pLength, $padstring, STR_PAD_BOTH));
  }

  
  public function padLeft($pLength, $pPadString = ' ')
  {
    $padstring = $this->getPHPString($pPadString);

    return new StringObj(\StringOperations::pad($this->string, $pLength, $padstring, STR_PAD_LEFT));
  }

  
  public function padRight($pLength, $pPadString = ' ')
  {
    $padstring = $this->getPHPString($pPadString);

    return new StringObj(\StringOperations::pad($this->string, $pLength, $padstring, STR_PAD_RIGHT));
  }
}