class FileExampleSessionStreamWrapper implements BackdropStreamWrapperInterface {
  
  public $context;
  
  protected $uri;
  
  protected $sessionContent;
  
  protected $directoryPointer;
  
  protected $directoryKeys;
  
  protected $streamPointer;
  
  public function __construct() {
    $_SESSION['file_example']['.isadir.txt'] = TRUE;
  }
  
  public function setUri($uri) {
    $this->uri = $uri;
  }
  
  public function getUri() {
    return $this->uri;
  }
  
  public function getTarget($uri = NULL) {
    if (!isset($uri)) {
      $uri = $this->uri;
    }
    list($scheme, $target) = explode('://', $uri, 2);
            return trim($target, '\/');
  }
  
  public static function getMimeType($uri, $mapping = NULL) {
    if (!isset($mapping)) {
                  include_once BACKDROP_ROOT . '/core/includes/file.mimetypes.inc';
      $mapping = file_mimetype_mapping();
    }
    $extension = '';
    $file_parts = explode('.', basename($uri));
        array_shift($file_parts);
                        while ($additional_part = array_pop($file_parts)) {
      $extension = backdrop_strtolower($additional_part . ($extension ? '.' . $extension : ''));
      if (isset($mapping['extensions'][$extension])) {
        return $mapping['mimetypes'][$mapping['extensions'][$extension]];
      }
    }
    return 'application/octet-stream';
  }
  
  public function getDirectoryPath() {
    return '';
  }
  
  public function getExternalUrl() {
    $path = $this->getLocalPath();
    $url = url('examples/file_example/access_session/' . $path, array('absolute' => TRUE));
    return $url;
  }
  
  public function chmod($mode) {
    return TRUE;
  }
  
  public function realpath() {
    return 'session://' . $this->getLocalPath();
  }
  
  protected function getLocalPath($uri = NULL) {
    if (!isset($uri)) {
      $uri = $this->uri;
    }
    $path = str_replace('session://', '', $uri);
    $path = trim($path, '/');
    return $path;
  }
  
  public function stream_open($uri, $mode, $options, &$opened_path) {
    $this->uri = $uri;
                    $this->sessionContent = &$this->uri_to_session_key($uri);
        $this->streamPointer = 0;
    return TRUE;
  }
  
  protected function &uri_to_session_key($uri, $create = TRUE) {
            $fail = FALSE;
    $path = $this->getLocalPath($uri);
    $path_components = explode('/', $path);
        $var = &$_SESSION['file_example'];
        if (count($path_components) < 1) {
      return $var;
    }
            foreach ($path_components as $component) {
      if ($create || isset($var[$component])) {
        $var = &$var[$component];
      }
      else {
                        return $fail;
      }
    }
    return $var;
  }
  
  public function stream_lock($operation) {
    return TRUE;
  }
  
  public function stream_read($count) {
    if (is_string($this->sessionContent)) {
      $remaining_chars = backdrop_strlen($this->sessionContent) - $this->streamPointer;
      $number_to_read = min($count, $remaining_chars);
      if ($remaining_chars > 0) {
        $buffer = backdrop_substr($this->sessionContent, $this->streamPointer, $number_to_read);
        $this->streamPointer += $number_to_read;
        return $buffer;
      }
    }
    return FALSE;
  }
  
  public function stream_write($data) {
            $data = check_plain($data);
    $this->sessionContent = substr_replace($this->sessionContent, $data, $this->streamPointer);
    $this->streamPointer += backdrop_strlen($data);
    return backdrop_strlen($data);
  }
  
  public function stream_eof() {
    return FALSE;
  }
  
  public function stream_seek($offset, $whence) {
    if (backdrop_strlen($this->sessionContent) >= $offset) {
      $this->streamPointer = $offset;
      return TRUE;
    }
    return FALSE;
  }
  
  public function stream_flush() {
    return TRUE;
  }
  
  public function stream_tell() {
    return $this->streamPointer;
  }
  
  public function stream_stat() {
    return array(
      'size' => backdrop_strlen($this->sessionContent),
    );
  }
  
  public function stream_close() {
    $this->streamPointer = 0;
        unset($this->sessionContent);
    return TRUE;
  }
  
  public function unlink($uri) {
    $path = $this->getLocalPath($uri);
    $path_components = preg_split('/\//', $path);
    $fail = FALSE;
    $unset = '$_SESSION[\'file_example\']';
    foreach ($path_components as $component) {
      $unset .= '[\'' . $component . '\']';
    }
                eval("unset($unset);");
    return TRUE;
  }
  
  public function rename($from_uri, $to_uri) {
    $from_key = &$this->uri_to_session_key($from_uri);
    $to_key = &$this->uri_to_session_key($to_uri);
    if (is_dir($to_key) || is_file($to_key)) {
      return FALSE;
    }
    $to_key = $from_key;
    unset($from_key);
    return TRUE;
  }
  
  public function dirname($uri = NULL) {
    list($scheme, $target) = explode('://', $uri, 2);
    $target = $this->getTarget($uri);
    if (strpos($target, '/')) {
      $dirname = preg_replace('@/[^/]*$@', '', $target);
    }
    else {
      $dirname = '';
    }
    return $scheme . '://' . $dirname;
  }
  
  public function mkdir($uri, $mode, $options) {
        if (is_dir($uri) || is_file($uri)) {
      return FALSE;
    }
        $this->uri_to_session_key($uri, TRUE);
        $marker_uri = $uri . '/.isadir.txt';
    $this->uri_to_session_key($marker_uri, TRUE);
    return TRUE;
  }
  
  public function rmdir($uri, $options) {
    $path = $this->getLocalPath($uri);
    $path_components = preg_split('/\//', $path);
    $fail = FALSE;
    $unset = '$_SESSION[\'file_example\']';
    foreach ($path_components as $component) {
      $unset .= '[\'' . $component . '\']';
    }
        debug($unset, 'array element to be unset');
    eval("unset($unset);");
    return TRUE;
  }
  
  public function url_stat($uri, $flags) {
        $key = $this->uri_to_session_key($uri, FALSE);
        $return = FALSE;
    $mode = 0;
        if (is_array($key) && array_key_exists('.isadir.txt', $key)) {
            $mode = 0040000;
    }
    elseif ($key !== FALSE) {
            $mode = 0100000;
    }
    if ($mode) {
      $size = 0;
      if ($mode == 0100000) {
        $size = backdrop_strlen($key);
      }
            $mode |= 0777;
      $return = array(
        'dev' => 0,
        'ino' => 0,
        'mode' => $mode,
        'nlink' => 0,
        'uid' => 0,
        'gid' => 0,
        'rdev' => 0,
        'size' => $size,
        'atime' => 0,
        'mtime' => 0,
        'ctime' => 0,
        'blksize' => 0,
        'blocks' => 0,
      );
    }
    return $return;
  }
  
  public function dir_opendir($uri, $options) {
    $var = &$this->uri_to_session_key($uri, FALSE);
    if ($var === FALSE || !array_key_exists('.isadir.txt', $var)) {
      return FALSE;
    }
            $this->directoryKeys = array_flip(array_keys($var));
    unset($this->directoryKeys['.isadir.txt']);
    $this->directoryKeys = array_keys($this->directoryKeys);
    $this->directoryPointer = 0;
    return TRUE;
  }
  
  public function dir_readdir() {
    if ($this->directoryPointer < count($this->directoryKeys)) {
      $next = $this->directoryKeys[$this->directoryPointer];
      $this->directoryPointer++;
      return $next;
    }
    return FALSE;
  }
  
  public function dir_rewinddir() {
    $this->directoryPointer = 0;
    return TRUE;
  }
  
  public function dir_closedir() {
    $this->directoryPointer = 0;
    unset($this->directoryKeys);
    return TRUE;
  }
}