<?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 mod_datalynx
 * @copyright 2013 onwards edulabs.org and associated programmers
 * @copyright based on the work  by 2011 Itamar Tzadok
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */

/**
 * Define all the backup steps that will be used by the backup_datalynx_activity_task
 */

/**
 * Define the complete data structure for backup, with file and id annotations
 */
class backup_datalynx_activity_structure_step extends backup_activity_structure_step {
    /**
     * Define the complete data structure for backup, with file and id annotations.
     *
     * @return backup_nested_element
     */
    protected function define_structure() {
        global $DB;
        global $CFG;

        // To know if we are including userinfo.
        $userinfo = $this->get_setting_value('userinfo');

        // Define each element separated.
        $datalynx = new backup_nested_element(
            'datalynx',
            ['id'],
            ['name', 'intro', 'introformat', 'timemodified', 'timeavailable', 'timedue',
                        'timeinterval', 'intervalcount', 'allowlate', 'grade', 'grademethod',
                        'anonymous', 'notification', 'notificationformat', 'entriesrequired',
                        'entriestoview', 'maxentries', 'timelimit', 'approval', 'grouped', 'rating',
                        'comments', 'locks', 'singleedit', 'singleview', 'rssarticles', 'rss', 'css',
                        'cssincludes', 'js', 'jsincludes', 'defaultview', 'defaultfilter',
                        'completionentries',
            ]
        );

        $module = new backup_nested_element('module', ['id'], ['groupmode']);

        $fields = new backup_nested_element('fields');
        $field = new backup_nested_element(
            'field',
            ['id'],
            ['type', 'name', 'description', 'visible', 'edits', 'label', 'param1',
                        'param2', 'param3', 'param4', 'param5', 'param6', 'param7', 'param8', 'param9',
                        'param10', 'targetcourse', 'targetinstance', 'targetview', 'targetfilter',
            ]
        );

        $filters = new backup_nested_element('filters');
        $filter = new backup_nested_element(
            'filter',
            ['id'],
            ['name', 'description', 'visible', 'perpage', 'selection', 'groupby', 'search',
                        'customsort', 'customsearch',
            ]
        );

        $customfilters = new backup_nested_element('customfilters');
        $customfilter = new backup_nested_element(
            'customfilter',
            ['id'],
            ['name', 'description', 'visible', 'fulltextsearch', 'timecreated', 'timecreatedsortable',
                        'timemodified', 'timemodifiedsortable', 'authorsearch', 'approve', 'status', 'fieldlist',
            ]
        );

        $views = new backup_nested_element('views');
        $view = new backup_nested_element(
            'view',
            ['id'],
            ['type', 'name', 'description', 'visible', 'perpage', 'groupby', 'filter',
                        'patterns', 'section', 'sectionpos', 'param1', 'param2', 'param3', 'param4',
                        'param5', 'param6', 'param7', 'param8', 'param9', 'param10',
            ]
        );

        $rules = new backup_nested_element('rules');
        $rule = new backup_nested_element(
            'rule',
            ['id'],
            ['type', 'name', 'description', 'enabled', 'param1', 'param2', 'param3',
                        'param4', 'param5', 'param6', 'param7', 'param8', 'param9', 'param10',
            ]
        );

        $entries = new backup_nested_element('entries');
        $entry = new backup_nested_element(
            'entry',
            ['id'],
            ['userid', 'groupid', 'timecreated', 'timemodified', 'approved', 'status',
            ]
        );

        $contents = new backup_nested_element('contents');
        $content = new backup_nested_element(
            'content',
            ['id'],
            ['fieldid', 'content', 'content1', 'content2', 'content3', 'content4']
        );

        $tags = new backup_nested_element('tags');
        $tag = new backup_nested_element('tag', ['id'], ['rawname']);

        $ratings = new backup_nested_element('ratings');
        $rating = new backup_nested_element(
            'rating',
            ['id'],
            ['component', 'ratingarea', 'scaleid', 'value', 'userid', 'timecreated',
                        'timemodified',
            ]
        );

        $grades = new backup_nested_element('grades');
        $grade = new backup_nested_element(
            'grade',
            ['id'],
            ['component', 'ratingarea', 'scaleid', 'value', 'userid', 'timecreated',
                        'timemodified',
            ]
        );

        $behaviors = new backup_nested_element('behaviors');
        $behavior = new backup_nested_element(
            'behavior',
            ['id'],
            ['dataid', 'name', 'description', 'visibleto', 'editableby', 'required',
            ]
        );

        $renderers = new backup_nested_element('renderers');
        $renderer = new backup_nested_element(
            'renderer',
            ['id'],
            ['dataid', 'type', 'name', 'description', 'notvisibletemplate',
                        'displaytemplate', 'novaluetemplate', 'edittemplate', 'noteditabletemplate',
            ]
        );

        // Build the tree.
        $datalynx->add_child($module);

        $datalynx->add_child($fields);
        $fields->add_child($field);

        $datalynx->add_child($filters);
        $filters->add_child($filter);

        $datalynx->add_child($customfilters);
        $customfilters->add_child($customfilter);

        $datalynx->add_child($views);
        $views->add_child($view);

        $datalynx->add_child($rules);
        $rules->add_child($rule);

        $datalynx->add_child($entries);
        $entries->add_child($entry);

        $entry->add_child($contents);
        $contents->add_child($content);

        $content->add_child($tags);
        $tags->add_child($tag);

        $entry->add_child($ratings);
        $ratings->add_child($rating);

        $datalynx->add_child($grades);
        $grades->add_child($grade);

        $datalynx->add_child($behaviors);
        $behaviors->add_child($behavior);

        $datalynx->add_child($renderers);
        $renderers->add_child($renderer);

        // Define sources.
        $datalynx->set_source_table('datalynx', ['id' => backup::VAR_ACTIVITYID]);
        $module->set_source_table('course_modules', ['id' => backup::VAR_MODID]);

        // Tags.
        $tag->set_source_sql('SELECT t.id, t.rawname
                        FROM {tag} t
                        JOIN {tag_instance} ti ON ti.tagid = t.id
                       WHERE ti.itemtype = ?
                         AND ti.component = ?
                         AND ti.itemid = ?', [
                backup_helper::is_sqlparam('datalynx_contents'),
                backup_helper::is_sqlparam('mod_datalynx'),
                backup::VAR_PARENTID]);

        if ($CFG->dbtype == 'mysqli' || $CFG->dbtype == 'mysql' || $CFG->dbtype == 'mariadb') {
            $field->set_source_sql(
                "SELECT f.*,
                        CASE f.type WHEN 'datalynxview' THEN MAX(c.fullname) ELSE NULL END AS targetcourse,
                        CASE f.type WHEN 'datalynxview' THEN MAX(d.name) ELSE NULL END AS targetinstance,
                        CASE f.type WHEN 'datalynxview' THEN MAX(v.name) ELSE NULL END AS targetview,
                        CASE f.type WHEN 'datalynxview' THEN MAX(fil.name) ELSE NULL END AS targetfilter
                   FROM {datalynx_fields} f
              LEFT JOIN {datalynx} d ON " . $DB->sql_cast_char2int('f.param1') . " = d.id
              LEFT JOIN {course_modules} cm ON cm.instance = d.id
              LEFT JOIN {course} c ON cm.course = c.id
              LEFT JOIN {datalynx_views} v ON " . $DB->sql_cast_char2int('f.param2') . " = v.id
              LEFT JOIN {datalynx_filters} fil ON " . $DB->sql_cast_char2int('f.param3') . " = fil.id
                  WHERE f.dataid = :dataid
               GROUP BY f.id",
                ['dataid' => backup::VAR_PARENTID]
            );
        } else {
                $field->set_source_sql(
                    "SELECT f.*
               FROM {datalynx_fields} f
              WHERE f.dataid = :dataid
                AND f.type != 'datalynxview'",
                    ['dataid' => backup::VAR_PARENTID]
                );
        }

        $filter->set_source_table('datalynx_filters', ['dataid' => backup::VAR_PARENTID]);
        $customfilter->set_source_table('datalynx_customfilters', ['dataid' => backup::VAR_PARENTID]);
        $view->set_source_table('datalynx_views', ['dataid' => backup::VAR_PARENTID]);
        $rule->set_source_table('datalynx_rules', ['dataid' => backup::VAR_PARENTID]);
        $behavior->set_source_table('datalynx_behaviors', ['dataid' => backup::VAR_PARENTID]);
        $renderer->set_source_table('datalynx_renderers', ['dataid' => backup::VAR_PARENTID]);

        // All the rest of elements only happen if we are including user info.
        if ($userinfo) {
            $entry->set_source_table('datalynx_entries', ['dataid' => backup::VAR_PARENTID]);
            $content->set_source_table(
                'datalynx_contents',
                ['entryid' => backup::VAR_PARENTID]
            );

            // Entry ratings.
            $rating->set_source_table(
                'rating',
                ['contextid' => backup::VAR_CONTEXTID,
                            'itemid' => backup::VAR_PARENTID,
                            'component' => backup_helper::is_sqlparam('mod_datalynx'),
                            'ratingarea' => backup_helper::is_sqlparam('entry'),
                ]
            );
            $rating->set_source_alias('rating', 'value');

            // Activity grade.
            $grade->set_source_table(
                'rating',
                ['contextid' => backup::VAR_CONTEXTID,
                            'component' => backup_helper::is_sqlparam('mod_datalynx'),
                            'ratingarea' => backup_helper::is_sqlparam('activity'),
                ]
            );
            $grade->set_source_alias('rating', 'value');
        }

        // Define id annotations.
        $datalynx->annotate_ids('scale', 'grade');
        $datalynx->annotate_ids('scale', 'rating');

        $entry->annotate_ids('user', 'userid');
        $entry->annotate_ids('group', 'groupid');

        $rating->annotate_ids('scale', 'scaleid');
        $rating->annotate_ids('user', 'userid');

        // Define file annotations.
        $datalynx->annotate_files('mod_datalynx', 'intro', null); // This file area hasn't itemid.
        $view->annotate_files('mod_datalynx', 'viewsection', 'id'); // By view->id.
        for ($i = 2; $i <= 9; $i++) {
            $view->annotate_files('mod_datalynx', "viewparam{$i}", 'id'); // By view->id.
        }
        $content->annotate_files('mod_datalynx', 'content', 'id'); // By content->id.

        // Return the root element (data), wrapped into standard activity structure.
        return $this->prepare_activity_structure($datalynx);
    }
}
