<?php

namespace Mnv\Core\JSONParser\Parser;

use Exception;
use Mnv\Core\JSONParser\Exception\FileException;
/**
 * JSONParser для разбора HTML-таблицы
 *
 * @package JSONParser
 */
abstract class BaseParser implements IParser
{
    /**
     * Содержит проанализированный результат
     *
     * @access   private
     * @var      array
     */
    protected array $table_arr;

    /**
     * Определяет допустимое расширение файла
     *
     * @access   protected
     * @var      string
     */
    protected string $file_extension = '';

    /**
     * @param    string  $file_url   Path to file (optional)
     */
    public function __construct($file_url = NULL)
    {
        if (isset($file_url)) {
            $this->loadFile($file_url);
        }
    }

    /**
     * Получить значение указанной ячейки
     *
     * @param    int $row_num    Row number
     * @param    int $col    Column number
     * @param    int $val_only
     * @return   array
     * @throws   Exception  If the cell identified doesn't exist.
     */
    public function getCell($row_num, $col, $val_only = TRUE): array
    {
        // check whether the cell exists
        if (!$this->isCellExists($row_num, $col)) {
            throw new Exception('Cell '.$row_num.','.$col.' doesn\'t exist', FileException::CELL_NOT_FOUND);
        }
        return $this->table_arr[$row_num][$col];
    }

    /**
     * Получить данные указанного столбца в виде массива
     *
     * @param    int     $col    Column number
     * @param    bool    $val_only
     * @return   array
     * @throws   Exception           If the column requested doesn't exist.
     */
    public function getColumn($col, $val_only = TRUE): array
    {
        $col_arr = array();

        if(!$this->isColumnExists($col)){
            throw new Exception('Column '.$col.' doesn\'t exist', FileException::COLUMN_NOT_FOUND);
        }

        // получить указанный столбец в каждой строке
        foreach($this->table_arr as $row) {
            array_push($col_arr, $row[$col]);
        }

        // вернуть массив
        return $col_arr;
    }

    /**
     * Получить данные всех ячеек в виде массива
     *
     * @param    bool    $val_only
     * @return   array
     * @throws   Exception   If the field is not set.
     */
    public function getField($val_only = TRUE): ?array
    {
        if (!$this->isFieldExists()) {
            // throw new \Exception('Field is not set', FileException::FIELD_NOT_FOUND);
            return null;
        }

        // вернуть массив
        return $this->table_arr;
    }

    /**
     * Получить данные указанной строки в виде массива
     *
     * @param    int     $row_num    Row number
     * @param    bool    $val_only
     * @return   array
     * @throws   Exception           When a row is requested that doesn't exist.
     */
    public function getRow($row_num, $val_only = TRUE): array
    {
        if(!$this->isRowExists($row_num)) {
            throw new Exception('Row '.$row_num.' doesn\'t exist', FileException::ROW_NOT_FOUND);
        }

        return $this->table_arr[$row_num];
    }

    /**
     * Проверить, существует ли ячейка с указанной строкой и столбцом
     *
     * @param    int     $row_num    Row number
     * @param    int     $col       Column
     * @return   bool
     */
    public function isCellExists($row_num, $col): bool
    {
        return $this->isRowExists($row_num) && $this->isColumnExists($col);
    }

    /**
     * Проверить, существует ли указанный столбец
     *
     * @param    int     $col    Column
     * @return   bool
     */
    public function isColumnExists($col): bool
    {
        $exist = false;
        foreach ($this->table_arr as $row) {
            if (array_key_exists($col, $row)) {
                $exist = true;
            }
        }
        return $exist;
    }

    /**
     * Проверить, существует ли указанная строка
     *
     * @param    int     $row_num    Row number
     * @return   bool
     */
    public function isRowExists($row_num): bool
    {
        return array_key_exists($row_num, $this->table_arr);
    }

    /**
     * Проверить, существует ли таблица
     *
     * @return   bool
     */
    public function isFieldExists(): bool
    {
        return isset($this->table_arr);
    }

    /**
     * Проверьте, существует ли файл, действителен и доступен для чтения
     *
     * @param    string  $file_path  Path to file
     * @return   bool
     * @throws   Exception           If file being loaded doesn't exist
     * @throws   Exception           If file extension doesn't match
     * @throws   Exception           If error reading the file
     */
    public function isFileReady($file_path): bool
    {
        // file exists?
        if (!file_exists($file_path)) {
            throw new Exception('File '.$file_path.' doesn\'t exist', FileException::FILE_NOT_FOUND);

            // extension valid?
        } else if (strtoupper(pathinfo($file_path, PATHINFO_EXTENSION)) != strtoupper($this->file_extension)){

            throw new Exception('File extension '.strtoupper(pathinfo($file_path, PATHINFO_EXTENSION)).' doesn\'t match with '.$this->file_extension, FileException::FILE_EXTENSION_MISMATCH);

            // file readable?
        } else if (($handle = fopen($file_path, 'r')) === FALSE) {

            throw new Exception('Error reading the file in'.$file_path, FileException::ERROR_READING_FILE);
            fclose($handle);

        } else {

            return TRUE;
        }
    }
}
