<?php
// This file is part of mod_datalynx for Moodle - http://moodle.org/
//
// It is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// It is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 *
 * @package datalynxview_grid
 * @subpackage grid
 * @copyright 2013 onwards edulabs.org and associated programmers
 * @copyright based on the work by 2012 Itamar Tzadok
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */

namespace datalynxview_grid;

use html_table;
use html_table_cell;
use html_table_row;
use html_writer;
use mod_datalynx\local\view\base;
use stdClass;

/**
 * Grid view class.
 *
 * @package    datalynxview_grid
 * @copyright  2013 onwards edulabs.org and associated programmers
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
class view extends base {
    /** @var string The view type. */
    protected string $type = 'grid';

    /** @var array The editors for this view. */
    protected array $editors = ['section', 'param2']; // phpcs:ignore

    /**
     * Returns a fieldset of view options
     */
    public function generate_default_view() {
        global $OUTPUT; // Needed for mustache implementation.

        // Get all the fields.
        $fields = $this->dl->get_fields();
        if (!$fields) {
            return; // You shouldn't get that far if there are no user fields.
        }

        // Remove fields that are used in fieldgroup.
        $fields = parent::remove_duplicates($fields);

        // Set views and filters menus and quick search.
        $table = new html_table();
        $table->attributes['cellpadding'] = '2';
        // First row: menus.
        $row1 = new html_table_row();
        $viewsmenu = new html_table_cell('##viewsmenu##');
        $seperator = new html_table_cell('     ');
        $filtersmenu = new html_table_cell('##filtersmenu##');
        $quicksearch = new html_table_cell('##quicksearch##');
        $quickperpage = new html_table_cell('##quickperpage##');
        $row1->cells = [$viewsmenu, $seperator, $filtersmenu, $quicksearch, $quickperpage];
        foreach ($row1->cells as $cell) {
            $cell->style = 'border:0 none;';
        }
        // Second row: add entries.
        $row2 = new html_table_row();
        $addentries = new html_table_cell('##addnewentry##');
        $addentries->colspan = 5;
        $row2->cells = [$addentries];
        foreach ($row2->cells as $cell) {
            $cell->style = 'border:0 none;';
        }
        // Third row: paging bar.
        $row3 = new html_table_row();
        $pagingbar = new html_table_cell('##pagingbar##');
        $pagingbar->colspan = 5;
        $row3->cells = [$pagingbar];
        foreach ($row3->cells as $cell) {
            $cell->style = 'border:0 none;';
        }
        // Construct the table.
        $table->data = [$row1, $row2, $row3];
        $sectiondefault = html_writer::table($table);
        $this->view->esection = html_writer::tag(
            'div',
            $sectiondefault,
            ['class' => 'mdl-align']
        ) . "<div>##entries##</div>";

        // Set content fields in responsive grid.
        $mustache = [];
        foreach ($fields as $field) {
            // Check if the fieldid is a generic field like approve or a user defined field.
            if (is_numeric($field->field->id) && $field->field->id > 0) {
                $thisfield['name'] = $field->name();
                $thisfield['tag'] = "[[{$field->name()}]]";
                $thisfield['size'] = 3; // Show four elements per row, extend if necessary.

                if ($field->type == "userinfo") {
                    $thisfield['tag'] = "##author:{$field->name()}##";
                }

                $mustache['fields'][] = $thisfield;
            }
        }
        $entrydefault = $OUTPUT->render_from_template('mod_datalynx/gridview', $mustache);
        $this->view->eparam2 = html_writer::tag('div', $entrydefault, ['class' => 'entry']);
    }

    /**
     * Apply the entry group layout.
     *
     * @param array $entriesset
     * @param string $name
     * @return array
     */
    protected function apply_entry_group_layout($entriesset, $name = '') {
        global $OUTPUT;

        $elements = [];

        // Prepare grid table if needed.
        if ($name != 'newentry' && !empty($this->view->param3)) {
            $entriescount = count($entriesset);
            [$cols, $rows] = explode(' ', $this->view->param3);
            if ($entriescount < $cols) {
                $cols = $entriescount;
                $rows = 1;
            } else {
                if ($rows) {
                    $rows = ceil($entriescount / $cols);
                } else {
                    $rows = 1;
                    $percol = ceil($entriescount / $cols) > 1 ? ceil($entriescount / $cols) : null;
                }
            }

            $table = $this->make_table($cols, $rows);
            $grouphtml = html_writer::table($table);
            // Now split $tablehtml to cells by ##begintablecell##.
            $cells = explode('##begintablecell##', $grouphtml);
            // The first part is everything before first cell.
            $elements[] = ['html', array_shift($cells)];
        }

        // Flatten the set to a list of elements.
        $count = 0;
        foreach ($entriesset as $entrydefinitions) {
            $elements = array_merge($elements, $entrydefinitions);
            if (!empty($cells)) {
                if (empty($percol) || $count >= $percol - 1) {
                    $count = 0;
                    $elements[] = ['html', array_shift($cells)];
                } else {
                    $count++;
                }
            }
        }

        // Add remaining cells.
        if (!empty($cells)) {
            foreach ($cells as $cell) {
                $elements[] = ['html', $cell];
            }
        }

        // Add group heading.
        $name = ($name == 'newentry') ? get_string('entrynew', 'datalynx') : $name;
        if ($name) {
            array_unshift($elements, ['html', $OUTPUT->heading($name, 3, 'main')]);
        }

        return $elements;
    }

    /**
     * Get the new entry definition.
     *
     * @param int $entryid
     * @return array
     */
    protected function new_entry_definition($entryid = -1) {
        $elements = [];

        // Get patterns definitions.
        $fields = $this->dl->get_fields();
        $tags = [];
        $patterndefinitions = [];
        $entry = new stdClass();
        foreach ($this->tags['field'] as $fieldid => $patterns) {
            if (isset($fields[$fieldid])) {
                $field = $fields[$fieldid];
                $entry->id = $entryid;
                $options = ['edit' => true, 'manage' => true];
                if ($fielddefinitions = $field->get_definitions($patterns, $entry, $options)) {
                    $patterndefinitions = array_merge($patterndefinitions, $fielddefinitions);
                }
                $tags = array_merge($tags, $patterns);
            }
        }

        // Split the entry template to tags and html.
        $parts = $this->split_template_by_tags($tags, $this->view->eparam2);

        foreach ($parts as $part) {
            if (in_array($part, $tags)) {
                if ($def = $patterndefinitions[$part]) {
                    $elements[] = $def;
                }
            } else {
                $elements[] = ['html', $part];
            }
        }

        return $elements;
    }

    /**
     * Make a table for the grid layout.
     *
     * @param int $cols
     * @param int $rows
     * @return html_table
     */
    protected function make_table($cols, $rows) {
        $table = new html_table();
        $table->align = array_fill(0, $cols, 'center');
        for ($r = 0; $r < $rows; $r++) {
            $row = new html_table_row();
            for ($c = 0; $c < $cols; $c++) {
                $cell = new html_table_cell();
                $cell->text = '##begintablecell##';
                $row->cells[] = $cell;
            }
            $table->data[] = $row;
        }

        return $table;
    }
}
