'use strict';
//avoid 304 http code:
app.set('etag', false);
//load files:
var fs = require('fs');
//Fuse search with logical operators

var Fuse = require('fuse-operators');
var files = [];
let jsonFiles = [];
var releases = [];
jsonFiles.releases = releases;

exports.loadFiles = function loadFiles(folder) {
    return new Promise(function (resolve, reject) {
        fs.readdir(folder, function (err, items) {
            items.forEach(element => {
                if (element.search(/json/i) > 0) {
                    files.push(element); //remove .json extension to display : the file name MUST be the same as release name
                }
            });
            resolve(files);
        });
    }).then(function (files) {
        files.forEach(element => {
            var json = fs.readFileSync(folder + '/' + element);
            jsonFiles.releases.push(JSON.parse(json));
        });
    });
};
exports.load_releases = function (req, res) {
    res.send(jsonFiles.releases);
    res.end();
};
exports.list_all_releases = function (req, res) {
    var json = [];

    search(req, res);
};
function filterReleases(searchProduct, searchReleases) {
    return new Promise(function (resolve, reject) {
        let json = [];

        json.push(
            jsonFiles.releases.filter(function (e) {
                return e.product == searchProduct && searchReleases.includes(e.name);
            }),
        );

        resolve(json);
    });
}
function filterTypes(searchType, json) {
    return new Promise(function (resolve, reject) {
        let a = [];
        json.forEach(releaseByProduct => {
            releaseByProduct.forEach(release => {
                var v = [];
                searchType.forEach(searchedType => {
                    v.push(
                        release.items.filter(function (e) {
                            return e.issueType == searchedType;
                        }),
                    );
                });
                v.forEach(e => {
                    e.forEach(i => {
                        a.push(i);
                    });
                });
            });
        });
        resolve(a);
    });
}
function filerProductArea(searchProductArea, json) {
    return new Promise(function (resolve, reject) {
        json = json.filter(function (e) {
            return searchProductArea.includes(e.productArea);
        });
        resolve(json);
    });
}
function filterText(searchFuzzy, searchFields, searchFieldsText, json) {
    return new Promise(function (resolve, reject) {
        let keys;
        if (searchFields == 'index') keys = ['key'];
        if (searchFields == 'objects') keys = ['objects.name', 'objects.meta'];
        if (searchFields == 'all') keys = ['summary', 'releaseNote', 'solutionDetails', 'objects.name', 'index'];

        if (searchFuzzy == 'true' && searchFieldsText) {
            var options = {
                keys: keys,

                shouldSort: true,
                threshold: 0.3,
                distance: 1000000,
                location: 0,
            };

            json = new Fuse(decodeURI(searchFieldsText), json, options);
        } else if (searchFieldsText) {
            searchFieldsText = decodeURI(searchFieldsText);
            var re = new RegExp(searchFieldsText, 'i');
            var v = [];
            let a = [];

            v.push(
                json.filter(function (e) {
                    if (searchFields == 'index') return e.key == searchFieldsText;

                    if (searchFields == 'objects' || 'all') {
                        let ok = false;
                        if (e.objects)
                            e.objects.forEach(element => {
                                if (
                                    (element.name && element.name.match(re)) ||
                                    (element.meta && element.meta.match(re))
                                ) {
                                    ok = true;
                                }
                            });
                        if (ok == true) {
                            return e;
                        }
                    }
                    if (searchFields == 'all') {
                        let ok = false;

                        ok = false;
                        for (var key in e) {
                            var value = e[key];

                            if (typeof value === 'string' || value instanceof String) {
                                if (value.match(re)) ok = true;
                            }

                            if (ok == true) {
                                return e;
                            }
                        }

                        return ok;
                    }
                }),
            );

            json = v[0];
        }
        resolve(json);
    });
}
function onlyUnique(value, index, self) {
    return self.indexOf(value) === index;
}
function search(req, res) {
    let json = [];
    var searchFuzzy = req.query.searchFuzzy;
    var searchProduct = req.query.searchProduct.split(',');
    var searchReleases = req.query.searchReleases.split(',');
    var searchProductArea = req.query.searchProductArea.split(',');
    var searchType = req.query.searchType.split(',');
    var searchFieldsText = decodeURI(req.query.searchFieldsText);
    let searchFields = req.query.searchFields;

    filterReleases(searchProduct, searchReleases).then(function (result) {
        json = result;

        filterTypes(searchType, json).then(function (result) {
            json = result;

            // hack to be able to select issue without product area
            const nullIndex = searchProductArea.findIndex(e=>e==='null');
            if (nullIndex == -1) {
                searchProductArea.push(null);
            }
            else searchProductArea[nullIndex] = null;

            filerProductArea(searchProductArea, json).then(function (result) {
                json = result;

                filterText(searchFuzzy, searchFields, searchFieldsText, json).then(function (result) {
                    res.send(result);
                    res.end();
                });
            });
        });
    });
}
