<?php

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

declare(strict_types=1);

namespace Apache\Avro\IO;

use Apache\Avro\AvroIO;

/**
 * AvroIO wrapper for string access
 */
class AvroStringIO implements AvroIO, \Stringable
{
    private string $stringBuffer;
    /**
     * @var int  current position in string
     */
    private int $currentIndex;
    /**
     * @var bool whether or not the string is closed.
     */
    private bool $isClosed;

    /**
     * @param string $str initial value of AvroStringIO buffer. Regardless
     *                    of the initial value, the pointer is set to the
     *                    beginning of the buffer.
     */
    public function __construct(string $str = '')
    {
        $this->isClosed = false;
        $this->stringBuffer = $str;
        $this->currentIndex = 0;
    }

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

    /**
     * Append bytes to this buffer.
     * (Nothing more is needed to support Avro.)
     * @param string $bytes bytes to write
     * @throws AvroIOException if $args is not a string value.
     * @return int count of bytes written.
     */
    public function write(string $bytes): int
    {
        $this->checkClosed();

        return $this->appendStr($bytes);
    }

    /**
     * @return bool true if this buffer is closed and false otherwise.
     */
    public function isClosed(): bool
    {
        return $this->isClosed;
    }

    /**
     * @todo test for fencepost errors wrt updating current_index
     * @param mixed $len
     * @return string bytes read from buffer
     */
    public function read($len): string
    {
        $this->checkClosed();
        $read = '';
        for ($i = $this->currentIndex; $i < ($this->currentIndex + $len); $i++) {
            $read .= $this->stringBuffer[$i] ?? '';
        }
        if (strlen($read) < $len) {
            $this->currentIndex = $this->length();
        } else {
            $this->currentIndex += $len;
        }

        return $read;
    }

    /**
     * @return int count of bytes in the buffer
     * @internal Could probably memoize length for performance, but
     *           no need do this yet.
     */
    public function length(): int
    {
        return strlen($this->stringBuffer);
    }

    /**
     * @throws AvroIOException if the seek failed.
     * @return bool true if successful
     */
    public function seek(int $offset, int $whence = self::SEEK_SET): bool
    {
        // Prevent seeking before BOF
        switch ($whence) {
            case self::SEEK_SET:
                if (0 > $offset) {
                    throw new AvroIOException('Cannot seek before beginning of file.');
                }
                $this->currentIndex = $offset;

                break;
            case self::SEEK_CUR:
                if (0 > $this->currentIndex + $offset) {
                    throw new AvroIOException('Cannot seek before beginning of file.');
                }
                $this->currentIndex += $offset;

                break;
            case self::SEEK_END:
                if (0 > $this->length() + $offset) {
                    throw new AvroIOException('Cannot seek before beginning of file.');
                }
                $this->currentIndex = $this->length() + $offset;

                break;
            default:
                throw new AvroIOException(sprintf('Invalid seek whence %d', $whence));
        }

        return true;
    }

    /**
     * @see AvroIO::tell()
     */
    public function tell(): int
    {
        return $this->currentIndex;
    }

    /**
     * @see AvroIO::isEof()
     */
    public function isEof(): bool
    {
        return $this->currentIndex >= $this->length();
    }

    /**
     * No-op provided for compatibility with AvroIO interface.
     * @return bool true
     */
    public function flush(): bool
    {
        return true;
    }

    /**
     * Marks this buffer as closed.
     */
    public function close(): bool
    {
        $this->checkClosed();
        $this->isClosed = true;

        return true;
    }

    /**
     * Truncates the truncate buffer to 0 bytes and returns the pointer
     * to the beginning of the buffer.
     * @return bool true
     */
    public function truncate(): bool
    {
        $this->checkClosed();
        $this->stringBuffer = '';
        $this->currentIndex = 0;

        return true;
    }

    /**
     * @uses self::__toString()
     */
    public function string(): string
    {
        return (string) $this;
    }

    /**
     * @throws AvroIOException if the buffer is closed.
     */
    private function checkClosed(): void
    {
        if ($this->isClosed()) {
            throw new AvroIOException('Buffer is closed');
        }
    }

    /**
     * Appends bytes to this buffer.
     * @throws AvroIOException
     * @return int count of bytes written.
     */
    private function appendStr(string $str): int
    {
        $this->checkClosed();
        $this->stringBuffer .= $str;
        $len = strlen($str);
        $this->currentIndex += $len;

        return $len;
    }
}
