/**
 * Code to output a standardised report filtering panel. 
 *
 * Filters can be saved and loaded by each user. Additionally, filters can define permissions to a certain task, e.g. they can be used to define the 
 * context within which someone can verify. In this case they provide the "outer limit" of the available records. 
 * Requires a [map] control on the page. If you don't want a map, the current option is to include one anyway and use css to hide the #map-container div.
 *
 * @param array $readAuth Pass read authorisation tokens.
 * @param array $options Options array with the following possibilities:
 *   sharing - define the record sharing task that is being filtered against. Options are reporting (default), peer_review, verification, moderation, data_flow.
 *   context_id - can also be passed as URL parameter. Force the initial selection of a particular context (a record which has defines_permissions=true in the
 *   filters table. Set to "default" to select their profile verification settings when sharing=verification.
 *   filter_id - can also be passed as URL parameter. Force the initial selection of a particular filter record in the filters table. 
 *   filterTypes - allows control of the list of filter panels available, e.g. to turn one off. Associative array keyed by category
 *   so that the filter panels can be grouped (use a blank key if not required). The array values are an array of or strings with a comma separated list
 *   of the filter types to included in the category - options are what, where, when, who, quality, source.
 *   filter-#name# - set the initial value of a report filter parameter #name#. 
 *   allowLoad - set to false to disable the load bar at the top of the panel.
 *   allowSave - set to false to disable the save bar at the foot of the panel.
 *   presets - provide an array of preset filters to provide in the filters drop down. Choose from my-records, my-groups (uses
 *     your list of taxon groups in the user account), my-locality (uses your recording locality from the user account),
 *     my-groups-locality (uses taxon groups and recording locatlity from the user account).
 * @param integer $website_id The current website's warehouse ID.
 * @param string $hiddenStuff Output parameter which will contain the hidden popup HTML that will be shown
 * using fancybox during filter editing. Should be appended AFTER any form element on the page as nested forms are not allowed.
 */
function report_filter_panel($readAuth, $options, $website_id, &$hiddenStuff)
{
    iform_load_helpers(array('report_helper'));
    if (!empty($_POST['filter:sharing'])) {
        $options['sharing'] = $_POST['filter:sharing'];
    }
    $options = array_merge(array('sharing' => 'reporting', 'admin' => false, 'adminCanSetSharingTo' => array('R' => 'reporting', 'V' => 'verification'), 'allowLoad' => true, 'allowSave' => true, 'taxon_list_id' => variable_get('iform_master_checklist_id', 0), 'redirect_on_success' => '', 'presets' => array('my-records', 'my-queried-rejected-records', 'my-groups', 'my-locality', 'my-groups-locality')), $options);
    $options['sharing'] = report_filters_sharing_code_to_full_term($options['sharing']);
    $options['sharingCode'] = report_filters_full_term_to_sharing_code($options['sharing']);
    if (!preg_match('/^(reporting|peer_review|verification|data_flow|moderation)$/', $options['sharing'])) {
        return 'The @sharing option must be one of reporting, peer_review, verification, data_flow or moderation (currently ' . $options['sharing'] . ').';
    }
    report_helper::add_resource('reportfilters');
    report_helper::add_resource('validation');
    report_helper::add_resource('fancybox');
    if (defined('DRUPAL_CORE_COMPATIBILITY') && DRUPAL_CORE_COMPATIBILITY !== '7.x') {
        hostsite_add_library('collapse');
    }
    $filterData = report_filters_load_existing($readAuth, $options['sharingCode']);
    $existing = '';
    $contexts = '';
    // add some preset filters in
    foreach ($options['presets'] as $preset) {
        $title = false;
        switch ($preset) {
            case 'my-records':
                if (hostsite_get_user_field('id')) {
                    $title = lang::get('My records');
                }
                break;
            case 'my-queried-rejected-records':
                if (hostsite_get_user_field('id')) {
                    $title = lang::get('My rejected or queried records');
                }
                break;
            case 'my-groups':
                if (hostsite_get_user_field('taxon_groups')) {
                    $title = lang::get('Records in species groups I like to record');
                }
                break;
            case 'my-locality':
                if (hostsite_get_user_field('location')) {
                    $title = lang::get('Records in the locality I generally record in');
                }
                break;
            case 'my-groups-locality':
                if (hostsite_get_user_field('taxon_groups') && hostsite_get_user_field('location')) {
                    $title = lang::get('Records of my species groups in my locality');
                }
                break;
            default:
                throw new exception("Unsupported preset {$preset} for the filter panel");
        }
        if ($title) {
            $presetFilter = array('id' => $preset, 'title' => $title, 'defines_permissions' => 'f');
            $filterData[] = $presetFilter;
        }
    }
    if (count($options['presets'])) {
        if ($groups = hostsite_get_user_field('taxon_groups')) {
            data_entry_helper::$javascript .= "indiciaData.userPrefsTaxonGroups='" . implode(',', array_keys(unserialize($groups))) . "';\n";
        }
        if ($location = hostsite_get_user_field('location')) {
            data_entry_helper::$javascript .= "indiciaData.userPrefsLocation=" . $location . ";\n";
        }
    }
    $contextDefs = array();
    if ($options['sharing'] === 'verification') {
        // apply legacy verification settings from their profile
        $location_id = hostsite_get_user_field('location_expertise');
        $taxon_group_ids = hostsite_get_user_field('taxon_groups_expertise');
        $survey_ids = hostsite_get_user_field('surveys_expertise');
        if ($location_id || $taxon_group_ids || $survey_ids) {
            $selected = !empty($options['context_id']) && $options['context_id'] === 'default' ? 'selected="selected" ' : '';
            $contexts .= "<option value=\"default\" {$selected}>" . lang::get('My verification records') . "</option>";
            $def = array();
            if ($location_id) {
                // user profile geographic limits should always be based on an indexed location.
                $def['indexed_location_id'] = $location_id;
            }
            if ($taxon_group_ids) {
                $arr = unserialize($taxon_group_ids);
                $def['taxon_group_list'] = implode(',', $arr);
                $def['taxon_group_names'] = array();
                $groups = data_entry_helper::get_population_data(array('table' => 'taxon_group', 'extraParams' => $readAuth + array('id' => $arr)));
                foreach ($groups as $group) {
                    $def['taxon_group_names'][$group['id']] = $group['title'];
                }
            }
            if ($survey_ids) {
                $arr = unserialize($survey_ids);
                $def['survey_list'] = implode(',', array_filter($arr));
            }
            $contextDefs['default'] = $def;
        }
    }
    if (!empty($_GET['context_id'])) {
        $options['context_id'] = $_GET['context_id'];
    }
    if (!empty($_GET['filter_id'])) {
        $options['filter_id'] = $_GET['filter_id'];
    }
    if (!empty($_GET['filters_user_id'])) {
        $options['filters_user_id'] = $_GET['filters_user_id'];
    }
    foreach ($filterData as $filter) {
        if ($filter['defines_permissions'] === 't') {
            $selected = !empty($options['context_id']) && $options['context_id'] == $filter['id'] ? 'selected="selected" ' : '';
            $contexts .= "<option value=\"{$filter['id']}\" {$selected}>{$filter['title']}</option>";
            $contextDefs[$filter['id']] = json_decode($filter['definition']);
        } else {
            $selected = !empty($options['filter_id']) && $options['filter_id'] == $filter['id'] ? 'selected="selected" ' : '';
            $existing .= "<option value=\"{$filter['id']}\" {$selected}>{$filter['title']}</option>";
        }
    }
    $r = '<div id="standard-params" class="ui-widget">';
    if ($options['allowSave'] && $options['admin']) {
        if (empty($_GET['filters_user_id'])) {
            // new filter to create, so sharing type can be edited
            $reload = data_entry_helper::get_reload_link_parts();
            $reloadPath = $reload['path'];
            if (count($reload['params'])) {
                $reloadPath .= '?' . data_entry_helper::array_to_query_string($reload['params']);
            }
            $r .= "<form action=\"{$reloadPath}\" method=\"post\" />";
            $r .= data_entry_helper::select(array('label' => lang::get('Select filter type'), 'fieldname' => 'filter:sharing', 'lookupValues' => $options['adminCanSetSharingTo'], 'suffixTemplate' => 'nosuffix', 'afterControl' => '<input type="submit" value="Go"/>', 'default' => $options['sharingCode']));
            $r .= '</form>';
        } else {
            // existing filter to edit, type is therefore fixed. JS will fill these values in.
            $r .= '<p>' . lang::get('This filter is for <span id="sharing-type-label"></span>.') . '</p>';
            $r .= data_entry_helper::hidden_text(array('fieldname' => 'filter:sharing'));
        }
    }
    if ($options['allowLoad']) {
        $r .= '<div class="header ui-toolbar ui-widget-header ui-helper-clearfix"><div><span id="active-filter-label">' . lang::get('New report') . '</span></div><span class="changed" style="display:none" title="This filter has been changed">*</span>';
        $r .= '<div>';
        if ($contexts) {
            data_entry_helper::$javascript .= "indiciaData.filterContextDefs = " . json_encode($contextDefs) . ";\n";
            if (count($contextDefs) > 1) {
                $r .= '<label for="context-filter">' . lang::get('Context:') . "</label><select id=\"context-filter\">{$contexts}</select>";
            } else {
                $keys = array_keys($contextDefs);
                $r .= '<input type="hidden" id="context-filter" value="' . $keys[0] . '" />';
            }
        }
        $r .= '<label for="select-filter">' . lang::get('Filter:') . '</label><select id="select-filter"><option value="" selected="selected">' . lang::get('Select filter') . "...</option>{$existing}</select>";
        $r .= '<button type="button" id="filter-apply">' . lang::get('Apply') . '</button>';
        $r .= '<button type="button" id="filter-reset" class="disabled">' . lang::get('Reset') . '</button>';
        $r .= '<button type="button" id="filter-build">' . lang::get('Create a filter') . '</button></div>';
        $r .= '</div>';
        $r .= '<div id="filter-details" style="display: none">';
        $r .= '<img src="' . data_entry_helper::$images_path . 'nuvola/close-22px.png" width="22" height="22" alt="Close filter builder" title="Close filter builder" class="button" id="filter-done"/>' . "\n";
    } else {
        $r .= '<div id="filter-details">';
        if (!empty($options['filter_id'])) {
            $r .= "<input type=\"hidden\" id=\"select-filter\" value=\"{$options['filter_id']}\"/>";
        } elseif (!empty($options['filters_user_id'])) {
            $r .= "<input type=\"hidden\" id=\"select-filters-user\" value=\"{$options['filters_user_id']}\"/>";
        }
    }
    $r .= '<div id="filter-panes">';
    $filters = array('filter_what' => new filter_what(), 'filter_where' => new filter_where(), 'filter_when' => new filter_when(), 'filter_who' => new filter_who(), 'filter_occurrence_id' => new filter_occurrence_id(), 'filter_quality' => new filter_quality(), 'filter_source' => new filter_source());
    if (!empty($options['filterTypes'])) {
        $filterModules = array();
        foreach ($options['filterTypes'] as $category => $list) {
            // $list can be an array or comma separated list
            if (is_array($list)) {
                $list = implode(',', $list);
            }
            $paneNames = 'filter_' . str_replace(',', ',filter_', $list);
            $paneList = explode(',', $paneNames);
            $filterModules[$category] = array_intersect_key($filters, array_fill_keys($paneList, 1));
        }
    } else {
        $filterModules = array('' => $filters);
    }
    foreach ($filterModules as $category => $list) {
        if ($category) {
            $class = defined('DRUPAL_CORE_COMPATIBILITY') && DRUPAL_CORE_COMPATIBILITY === '7.x' ? '' : 'collapsible collapsed';
            $r .= "<fieldset class=\"{$class}\"><legend>" . $category . '</legend><div>';
        }
        foreach ($list as $moduleName => $module) {
            $r .= "<div class=\"pane\" id=\"pane-{$moduleName}\"><a class=\"fb-filter-link\" href=\"#controls-{$moduleName}\"><span class=\"pane-title\">" . $module->get_title() . '</span>';
            $r .= '<span class="filter-desc"></span></a>';
            $r .= "</div>";
        }
        if ($category) {
            $r .= '</div></fieldset>';
        }
    }
    $r .= '</div>';
    // filter panes
    $r .= '<div class="toolbar">';
    if ($options['allowSave']) {
        $r .= '<label for="filter:title">' . lang::get('Save filter as') . ':</label> <input id="filter:title" class="control-width-5"/>';
        if ($options['admin']) {
            $r .= '<br/>';
            if (empty($options['adminCanSetSharingTo'])) {
                throw new exception('Report standard params panel in admin mode so adminCanSetSharingTo option must be populated.');
            }
            $r .= data_entry_helper::autocomplete(array('label' => 'For who?', 'fieldname' => 'filters_user:user_id', 'table' => 'user', 'valueField' => 'id', 'captionField' => 'person_name', 'formatFunction' => "function(item) { return item.person_name + ' (' + item.email_address + ')'; }", 'extraParams' => $readAuth + array('view' => 'detail'), 'class' => 'control-width-5'));
            $r .= data_entry_helper::textarea(array('label' => 'Description', 'fieldname' => 'filter:description'));
        }
        $r .= '<img src="' . data_entry_helper::$images_path . 'nuvola/save-22px.png" width="22" height="22" alt="Save filter" title="Save filter" class="button" id="filter-save"/>';
        $r .= '<img src="' . data_entry_helper::$images_path . 'trash-22px.png" width="22" height="22" alt="Bin this filter" title="Bin this filter" class="button disabled" id="filter-delete"/>';
    }
    $r .= '</div></div>';
    // toolbar + clearfix
    report_helper::$javascript .= "indiciaData.lang={pleaseSelect:\"" . lang::get('Please select') . "\"};\n";
    // create the hidden panels required to populate the popups for setting each type of filter up.
    $hiddenStuff = '';
    foreach ($filterModules as $category => $list) {
        foreach ($list as $moduleName => $module) {
            $hiddenStuff .= "<div style=\"display: none\"><form id=\"controls-{$moduleName}\" action=\"#\" class=\"filter-controls\"><fieldset>" . $module->get_controls($readAuth, $options) . '<button class="fb-close" type="button">Cancel</button>' . '<button class="fb-apply" type="submit">Apply</button></fieldset></form></div>';
            $shortName = str_replace('filter_', '', $moduleName);
            report_helper::$javascript .= "indiciaData.lang.NoDescription{$shortName}='" . lang::get('Click to Filter ' . ucfirst($shortName)) . "';\n";
        }
    }
    $r .= '</div>';
    report_helper::$js_read_tokens = $readAuth;
    report_helper::$javascript .= "indiciaData.lang.CreateAFilter='" . lang::get('Create a filter') . "';\n";
    report_helper::$javascript .= "indiciaData.lang.ModifyFilter='" . lang::get('Modify filter') . "';\n";
    report_helper::$javascript .= "indiciaData.lang.FilterReport='" . lang::get('New report') . "';\n";
    report_helper::$javascript .= "indiciaData.lang.FilterSaved='" . lang::get('The filter has been saved') . "';\n";
    report_helper::$javascript .= "indiciaData.lang.FilterDeleted='" . lang::get('The filter has been deleted') . "';\n";
    report_helper::$javascript .= "indiciaData.lang.ConfirmFilterChangedLoad='" . lang::get('Do you want to load the selected filter and lose your current changes?') . "';\n";
    report_helper::$javascript .= "indiciaData.lang.FilterExistsOverwrite='" . lang::get('A filter with that name already exists. Would you like to overwrite it?') . "';\n";
    report_helper::$javascript .= "indiciaData.lang.AutochecksFailed='" . lang::get('Automated checks failed') . "';\n";
    report_helper::$javascript .= "indiciaData.lang.AutochecksPassed='" . lang::get('Automated checks passed') . "';\n";
    report_helper::$javascript .= "indiciaData.lang.HasPhotos='" . lang::get('Records which have photos') . "';\n";
    report_helper::$javascript .= "indiciaData.lang.ConfirmFilterDelete='" . lang::get('Are you sure you want to permanently delete the {title} filter?') . "';\n";
    report_helper::$javascript .= "indiciaData.lang.MyRecords='" . lang::get('My records only') . "';\n";
    report_helper::$javascript .= "indiciaData.filterPostUrl='" . iform_ajaxproxy_url(null, 'filter') . "';\n";
    report_helper::$javascript .= "indiciaData.filterAndUserPostUrl='" . iform_ajaxproxy_url(null, 'filter_and_user') . "';\n";
    report_helper::$javascript .= "indiciaData.filterSharing='" . strtoupper(substr($options['sharing'], 0, 1)) . "';\n";
    report_helper::$javascript .= "indiciaData.user_id='" . hostsite_get_user_field('indicia_user_id') . "';\n";
    report_helper::$javascript .= "indiciaData.website_id=" . $website_id . ";\n";
    report_helper::$javascript .= "indiciaData.redirectOnSuccess='{$options['redirect_on_success']}';\n";
    // load up the filter, BEFORE any AJAX load of the grid code. First fetch any URL param overrides.
    $overrideJs = '';
    foreach (array_merge($options, $_GET) as $key => $value) {
        if (substr($key, 0, 7) === 'filter-') {
            $overrideJs .= "indiciaData.filter.def['" . substr($key, 7) . "']='" . str_replace("'", "\\'", $value) . "';\n";
        }
    }
    if (!empty($overrideJs)) {
        $overrideJs .= "indiciaData.filter.orig=\$.extend({}, indiciaData.filter.def);\n";
        $overrideJs .= "applyFilterToReports(false);\n";
    }
    if (!empty($options['filters_user_id'])) {
        report_helper::$onload_javascript = "loadFilterUser({$options['filters_user_id']});\n" . $overrideJs . report_helper::$onload_javascript;
    } else {
        report_helper::$onload_javascript = "if (\$('#select-filter').val()) {" . "loadFilter(\$('#select-filter').val(), false);" . "};\n" . $overrideJs . report_helper::$onload_javascript;
    }
    return $r;
}