/**
 * Copyright (c) 2015 "Fronteer LTD"
 * Grasshopper Event Engine
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

var _ = require('lodash');

var GrassHopper = require('gh-core');
var GrassHopperUtil = require('gh-core/lib/util');

var OrgUnitAPI = require('./api');
var OrgUnitImport = require('./internal/import');

/**
 * @REST getOrgUnits
 *
 * Get the organisational units in the current app
 *
 * @Server      app
 * @Method      GET
 * @Path        /orgunit
 * @QueryParam  {boolean}           [includeSeries]         Whether to include the event series associated to the organisational units. Defaults to `false`
 * @QueryParam  {boolean}           [includePermissions]    Whether to include if the current user can manage the organisational units/series and whether an organisational unit is locked. Defaults to `false`
 * @QueryParam  {number}            [parent]                The id of the parent to retrieve the organisational units for
 * @QueryParam  {string[]}          [type]                  The organisational unit type[s] to filter the organisational unit by
 * @Return      {OrgUnit[]}                                 The organisational units in the current app
 */

/**
 * @REST getOrgUnitsByApp
 *
 * Get the organisational units in an app
 *
 * @Server      admin
 * @Method      GET
 * @Path        /orgunit
 * @QueryParam  {number}            app                     The id of the app to get the organisational units for
 * @QueryParam  {boolean}           [includeSeries]         Whether to include the event series associated to the organisational units. Defaults to `false`
 * @QueryParam  {boolean}           [includePermissions]    Whether to include if the current user can manage the organisational units/series and whether an organisational unit is locked. Defaults to `false`
 * @QueryParam  {number}            [parent]                The id of the parent to retrieve the organisational units for
 * @QueryParam  {string[]}          [type]                  The organisational unit type[s] to filter the organisational unit by
 * @Return      {OrgUnit[]}                                 The organisational units in the app
 */
var _getOrgUnits = function(req, res) {
    var appId = req.query.app || req.ctx.app.id;
    var types = GrassHopperUtil.toArray(req.query.type);

    OrgUnitAPI.getOrgUnits(req.ctx, appId, req.query.parent, types, req.query.includeSeries, req.query.includePermissions, function(err, orgUnits) {
        if (err) {
            return res.status(err.code).send(err.msg);
        }

        return res.status(200).send({'results': orgUnits});
    });
};

GrassHopper.appRouter.on('get', '/api/orgunit', _getOrgUnits);
GrassHopper.globalAdminRouter.on('get', '/api/orgunit', _getOrgUnits);

/**
 * @REST getOrgUnit
 *
 * Get an organisational unit
 *
 * @Server      admin,app
 * @Method      GET
 * @Path        /orgunit/{id}
 * @PathParam   {number}            id                  The id of the organisational unit to retrieve
 * @QueryParam  {boolean}           [includeSeries]     Whether to include the event series associated to the organisational unit. Defaults to `false`
 * @Return      {OrgUnit}                               The requested organisational unit
 */
var _getOrgUnit = function(req, res) {
    OrgUnitAPI.getOrgUnit(req.ctx, req.params.id, req.query.includeSeries, function(err, orgUnit) {
        if (err) {
            return res.status(err.code).send(err.msg);
        }

        return res.status(200).send(orgUnit);
    });
};

GrassHopper.globalAdminRouter.on('get', '/api/orgunit/:id', _getOrgUnit);
GrassHopper.appRouter.on('get', '/api/orgunit/:id', _getOrgUnit);

/**
 * @REST getOrgUnitSeries
 *
 * Get the event series in an organisational unit
 *
 * @Server      admin,app
 * @Method      GET
 * @Path        /orgunit/{id}/series
 * @PathParam   {number}            id                  The id of the organisational unit to retrieve the event series for
 * @QueryParam  {number}            [limit]             The maximum number of results to retrieve. Default: 10
 * @QueryParam  {number}            [offset]            The paging number of the results to retrieve
 * @QueryParam  {boolean}           [upcoming]          Whether to only include event series with upcoming events. Defaults to `false`
 * @Return      {SeriesList}                            The event series in the organisational unit
 */
var _getOrgUnitSeries = function(req, res) {
    OrgUnitAPI.getOrgUnitSeries(req.ctx, req.params.id, req.query.limit, req.query.offset, req.query.upcoming, function(err, series) {
        if (err) {
            return res.status(err.code).send(err.msg);
        }

        return res.status(200).send(series);
    });
};

GrassHopper.globalAdminRouter.on('get', '/api/orgunit/:id/series', _getOrgUnitSeries);
GrassHopper.appRouter.on('get', '/api/orgunit/:id/series', _getOrgUnitSeries);

/**
 * @REST getOrgUnitCalendar
 *
 * Get the calendar for an organisational unit
 *
 * @Server      admin,app
 * @Method      GET
 * @Path        /orgunit/{id}/calendar
 * @PathParam   {number}            id                  The id of the organisational unit to get the calendar for
 * @QueryParam  {string}            start               The timestamp (ISO 8601) from which to get the calendar for the organisation unit
 * @QueryParam  {string}            end                 The timestamp (ISO 8601) until which to get the calendar for the organisation unit
 * @Return      {Event[]}                               The requested organisational unit calendar
 */
var _getOrgUnitCalendar = function(req, res) {
    OrgUnitAPI.getOrgUnitCalendar(req.ctx, req.params.id, req.query.start, req.query.end, function(err, events) {
        if (err) {
            return res.status(err.code).send(err.msg);
        }

        return res.status(200).send({'results': events});
    });
};

GrassHopper.globalAdminRouter.on('get', '/api/orgunit/:id/calendar', _getOrgUnitCalendar);
GrassHopper.appRouter.on('get', '/api/orgunit/:id/calendar', _getOrgUnitCalendar);

/**
 * @REST getOrgUnitCalendarIcal
 *
 * Get the calendar for an organisational unit in iCal
 *
 * @Server      admin,app
 * @Method      GET
 * @Path        /orgunit/{id}/calendar.ical
 * @PathParam   {number}            id                  The id of the organisational unit to get the calendar for in iCal format
 * @Return      {ical}                                  The requested organisational unit calendar in iCal format
 */
var _getOrgUnitCalendarIcal = function(req, res) {
    OrgUnitAPI.getOrgUnitCalendarIcal(req.ctx, req.params.id, function(err, ical) {
        if (err) {
            return res.status(err.code).send(err.msg);
        }

        res.set('Content-Type', 'text/calendar');
        return res.status(200).send(ical);
    });
};

GrassHopper.globalAdminRouter.on('get', '/api/orgunit/:id/calendar.ical', _getOrgUnitCalendarIcal);
GrassHopper.appRouter.on('get', '/api/orgunit/:id/calendar.ical', _getOrgUnitCalendarIcal);

/**
 * @REST getOrgUnitCalendarRss
 *
 * Get the calendar for an organisational unit in RSS
 *
 * @Server      admin,app
 * @Method      GET
 * @Path        /orgunit/{id}/calendar.rss
 * @PathParam   {number}            id                  The id of the organisational unit to get the calendar for in RSS format
 * @Return      {rss}                                   The requested organisational unit calendar in RSS format
 */
var _getOrgUnitCalendarRss = function(req, res) {
    OrgUnitAPI.getOrgUnitCalendarRss(req.ctx, req.params.id, function(err, rss) {
        if (err) {
            return res.status(err.code).send(err.msg);
        }

        res.set('Content-Type', 'application/rss+xml');
        return res.status(200).send(rss);
    });
};

GrassHopper.globalAdminRouter.on('get', '/api/orgunit/:id/calendar.rss', _getOrgUnitCalendarRss);
GrassHopper.appRouter.on('get', '/api/orgunit/:id/calendar.rss', _getOrgUnitCalendarRss);

/**
 * @REST getOrgUnitUpcoming
 *
 * Get the upcoming events in an organisational unit
 *
 * @Server      admin,app
 * @Method      GET
 * @Path        /orgunit/{id}/upcoming
 * @PathParam   {number}            id                  The id of the organisational unit to get the upcoming events for
 * @QueryParam  {number}            [limit]             The maximum number of results to retrieve. Default: 10
 * @QueryParam  {number}            [offset]            The paging number of the results to retrieve
 * @Return      {EventList}                             The upcoming events in the organisational unit
 */
var _getOrgUnitUpcoming = function(req, res) {
    res.sendStatus(501);
};

GrassHopper.globalAdminRouter.on('get', '/api/orgunit/:id/upcoming', _getOrgUnitUpcoming);
GrassHopper.appRouter.on('get', '/api/orgunit/:id/upcoming', _getOrgUnitUpcoming);

/**
 * @REST createOrgUnit
 *
 * Create a new organisational unit in the current app
 *
 * @Server      app
 * @Method      POST
 * @Path        /orgunit
 * @FormParam   {string}            displayName         The name of the organisational unit
 * @FormParam   {string}            type                The organisational unit type (e.g. `course`, `subject`, `part`, `module`)
 * @FormParam   {string}            [description]       The description of the organisational unit
 * @FormParam   {number}            [group]             The id of the group that can manage the organisational unit. Defaults to creating a new group with the current user as a member
 * @FormParam   {object|string}     [metadata]          The metadata of the organisational unit. When using a string, it should be a stringified JSON object
 * @FormParam   {number}            [parent]            The id of the parent organisational unit
 * @FormParam   {boolean}           [published]         The published flag of the organisational unit
 * @Return      {OrgUnit}                               The created organisational unit
 */

/**
 * @REST createOrgUnitByApp
 *
 * Create a new organisational unit in an app
 *
 * @Server      admin
 * @Method      POST
 * @Path        /orgunit
 * @FormParam   {number}            app                 The id of the app to create the organisational unit for
 * @FormParam   {string}            displayName         The name of the organisational unit
 * @FormParam   {string}            type                The organisational unit type (e.g. `course`, `subject`, `part`, `module`) Limited to 32 characters
 * @FormParam   {string}            [description]       The description of the organisational unit
 * @FormParam   {object|string}     [metadata]          The metadata of the organisational unit. When using a string, it should be a stringified JSON object
 * @FormParam   {number}            [group]             The id of the group that can manage the organisational unit. Defaults to creating a new group with the current user as a member
 * @FormParam   {number}            [parent]            The id of the parent organisational unit
 * @FormParam   {boolean}           [published]         The published flag of the organisational unit
 * @Return      {OrgUnit}                               The created organisational unit
 */
var _createOrgUnit = function(req, res) {
    var appId = req.body.app || req.ctx.app.id;
    OrgUnitAPI.createOrgUnit(req.ctx, appId, req.body.displayName, req.body.type, req.body.description, req.body.metadata, req.body.published, req.body.group, req.body.parent, function(err, orgUnit) {
        if (err) {
            return res.status(err.code).send(err.msg);
        }

        return res.status(201).send(orgUnit);
    });
};
GrassHopper.appRouter.on('post', '/api/orgunit', _createOrgUnit);
GrassHopper.globalAdminRouter.on('post', '/api/orgunit', _createOrgUnit);

/**
 * @REST updateOrgUnit
 *
 * Update an organisational unit
 *
 * @Server      admin,app
 * @Method      POST
 * @Path        /orgunit/{id}
 * @PathParam   {number}            id                  The id of the organisational unit to update
 * @FormParam   {string}            [description]       Updated organisational unit description
 * @FormParam   {string}            [displayName]       Updated organisational unit name
 * @FormParam   {number}            [group]             Updated id of the group that can manage the organisational unit
 * @FormParam   {object|string}     [metadata]          The metadata of the organisational unit. When using a string, it should be a stringified JSON object
 * @FormParam   {number}            [parent]            Updated id of the parent organisational unit
 * @FormParam   {string}            [type]              Updated organisational unit type (e.g. `course`, `subject`, `part`, `module`)
 * @FormParam   {boolean}           [published]         Updated published flag of the organisational unit
 * @Return      {OrgUnit}                               The updated organisational unit
 */
var _updateOrgUnit = function(req, res) {
    OrgUnitAPI.updateOrgUnit(req.ctx, req.params.id, req.body, function(err, orgUnit) {
        if (err) {
            return res.status(err.code).send(err.msg);
        }

        return res.status(200).send(orgUnit);
    });
};

GrassHopper.globalAdminRouter.on('post', '/api/orgunit/:id', _updateOrgUnit);
GrassHopper.appRouter.on('post', '/api/orgunit/:id', _updateOrgUnit);

/**
 * @REST addOrgUnitSeries
 *
 * Add an event series to an organisational unit
 *
 * @Server      admin,app
 * @Method      POST
 * @Path        /orgunit/{id}/series
 * @PathParam   {number}            id                  The id of the organisational unit to add an event series to
 * @FormParam   {number[]}          serie               The id of the event series to add to the organisational unit
 * @Return      {void}
 */
var _addOrgUnitSeries = function(req, res) {
    var series = GrassHopperUtil.toArray(req.body.serie);
    OrgUnitAPI.addOrgUnitSeries(req.ctx, req.params.id, series, function(err) {
        if (err) {
            return res.status(err.code).send(err.msg);
        }

        return res.sendStatus(200);
    });
};

GrassHopper.globalAdminRouter.on('post', '/api/orgunit/:id/series', _addOrgUnitSeries);
GrassHopper.appRouter.on('post', '/api/orgunit/:id/series', _addOrgUnitSeries);

/**
 * @REST addOrgUnitEvents
 *
 * Add an event to an organisational unit
 *
 * @Server      admin,app
 * @Method      POST
 * @Path        /orgunit/{id}/events
 * @PathParam   {number}            id                  The id of the organisational unit to add an event to
 * @FormParam   {number[]}          event               The id of the event to add to the organisational unit
 * @Return      {void}
 */
var _addOrgUnitEvents = function(req, res) {
    return res.sendStatus(501);
};

GrassHopper.globalAdminRouter.on('post', '/api/orgunit/:id/events', _addOrgUnitEvents);
GrassHopper.appRouter.on('post', '/api/orgunit/:id/events', _addOrgUnitEvents);

/**
 * @REST deleteOrgUnitSeries
 *
 * Remove an event series from an organisational unit
 *
 * @Server      admin,app
 * @Method      DELETE
 * @Path        /orgunit/{id}/series
 * @PathParam   {number}            id                  The id of the organisational unit to remove an event series from
 * @FormParam   {string[]}          serie               The id of the event series to remove from the organisational unit
 * @Return      {void}
 */
var _deleteOrgUnitSeries = function(req, res) {
    var series = GrassHopperUtil.toArray(req.body.serie);
    OrgUnitAPI.deleteOrgUnitSeries(req.ctx, req.params.id, series, function(err) {
        if (err) {
            return res.status(err.code).send(err.msg);
        }

        return res.sendStatus(200);
    });
};

GrassHopper.globalAdminRouter.on('delete', '/api/orgunit/:id/series', _deleteOrgUnitSeries);
GrassHopper.appRouter.on('delete', '/api/orgunit/:id/series', _deleteOrgUnitSeries);

/**
 * @REST deleteOrgUnitEvents
 *
 * Remove an event from an organisational unit
 *
 * @Server      admin,app
 * @Method      DELETE
 * @Path        /orgunit/{id}/events
 * @PathParam   {number}            id                  The id of the organisational unit to remove an event from
 * @FormParam   {string[]}          event               The id of the event to remove from the organisational unit
 * @Return      {void}
 */
var _deleteOrgUnitEvents = function(req, res) {
    res.sendStatus(501);
};

GrassHopper.globalAdminRouter.on('delete', '/api/orgunit/:id/events', _deleteOrgUnitEvents);
GrassHopper.appRouter.on('delete', '/api/orgunit/:id/events', _deleteOrgUnitEvents);

/**
 * @REST deleteOrgUnit
 *
 * Delete an organisational unit
 *
 * @Server      admin,app
 * @Method      DELETE
 * @Path        /orgunit/{id}
 * @PathParam   {number}            id                  The id of the organisational unit to delete
 * @Return      {void}
 */
var _deleteOrgUnit = function(req, res) {
    OrgUnitAPI.deleteOrgUnit(req.ctx, req.params.id, function(err) {
        if (err) {
            return res.status(err.code).send(err.msg);
        }

        return res.sendStatus(200);
    });
};

GrassHopper.globalAdminRouter.on('delete', '/api/orgunit/:id', _deleteOrgUnit);
GrassHopper.appRouter.on('delete', '/api/orgunit/:id', _deleteOrgUnit);

/**
 * @REST subscribeOrgUnit
 *
 * Subscribe to the event series and events in an organisational unit
 *
 * @Server      admin,app
 * @Method      POST
 * @Path        /orgunit/{id}/subscribe
 * @PathParam   {number}            id                  The id of the organisational unit to subscribe to the event series and events for
 * @FormParam   {number}            [userId]            The id of the user that should be subscribed. Defaults to the current user
 * @Return      {void}
 */
var _subscribeOrgUnit = function(req, res) {
    OrgUnitAPI.subscribeOrgUnit(req.ctx, req.params.id, req.body.userId, function(err) {
        if (err) {
            return res.status(err.code).send(err.msg);
        }

        return res.sendStatus(200);
    });
};

GrassHopper.globalAdminRouter.on('post', '/api/orgunit/:id/subscribe', _subscribeOrgUnit);
GrassHopper.appRouter.on('post', '/api/orgunit/:id/subscribe', _subscribeOrgUnit);

/**
 * @REST unsubscribeOrgUnit
 *
 * Unsubscribe from the event series and events in an organisational unit
 *
 * @Server      admin,app
 * @Method      POST
 * @Path        /orgunit/{id}/unsubscribe
 * @PathParam   {number}            id                  The id of the organisational unit to unsubscribe from
 * @FormParam   {number}            [userId]            The id of the user that should be unsubscribed. Defaults to the current user
 * @Return      {void}
 */
var _unsubscribeOrgUnit = function(req, res) {
    OrgUnitAPI.unsubscribeOrgUnit(req.ctx, req.params.id, req.body.userId, function(err) {
        if (err) {
            return res.status(err.code).send(err.msg);
        }

        return res.sendStatus(200);
    });
};

GrassHopper.globalAdminRouter.on('post', '/api/orgunit/:id/unsubscribe', _unsubscribeOrgUnit);
GrassHopper.appRouter.on('post', '/api/orgunit/:id/unsubscribe', _unsubscribeOrgUnit);

/**
 * @REST exportOrgUnit
 *
 * Export the organisational units, event series and events under an organisational unit
 *
 * The data can be exported in either JSON or CSV.
 *
 * The JSON export format is fairly straightforward and contains nested organisational units, series and events
 *
 * The CSV export will use the `type` of the organisational unit and the level on which it appears
 * as the column headers
 *
 * Lets look at the following Timetable tree:
 *
 * ```
 * - Asian and Middle Easter Studies (orgunit:course)
 *   -  Chinese Studies (orgunit:subject)
 *      - Part IB (orgunit:part)
 *         - Modern Chinese Texts (orgunit:module)
 *            - Lectures (series)
 *              - 03/11 by Sue Simpson
 *              - 10/11 by Sue Simpson
 *              - 17/11 by Sue Simpson
 *              - 24/11 by Sue Simpson
 *            - Practicals (series)
 *              - 04/11 by Mr Jack McJackerson and Dr Jill Jameson
 *              - 11/11 by Mr Jack McJackerson and Dr Jill Jameson
 *         - Literary Chinese (orgunit:module)
 *            - Classic of Poetry (series)
 *              - 05/11 by Sue Simpson
 *      - Part II (orgunit:part)
 *         - China and Warfare (orgunit:module)
 *           - Tang dynasty (series)
 *             - 12/01 by Dr Wing Lu
 *             - 19/01 by Dr Wing Lu
 * ```
 *
 * When exporting the entire course, the follwing CSV columns would be generated: (for brevity only
 * the id and displayName are included in the example):
 * ```
 * course_0_id, course_0_displayName, .., subject_1_id, subject_1_displayName, .., part_2_id, part_2_displayName, .., module_3_id, module_3_displayName, .., series_id, series_displayName, .., event_id, event_displayName, .., organiser_id, organiser_displayName
 * ```
 *
 * and the following data:
 * ```
 * course_0_id, course_0_displayName, .., subject_1_id, subject_1_displayName, .., part_2_id, part_2_displayName, .., module_3_id, module_3_displayName, .., series_id, series_displayName, .., event_id, event_displayName, .., organiser_id, organiser_displayName
 * 1, Asian and Middle Easter Studies   , 2, Chinese Studies,                    , 3      , Part IB,                , 4, Modern Chinese texts,             , 1, Lectures,                     1, 03/11,     1, Sue Simpson
 * 1, Asian and Middle Easter Studies   , 2, Chinese Studies,                    , 3      , Part IB,                , 4, Modern Chinese texts,             , 1, Lectures,                     2, 10/11,     1, Sue Simpson
 * 1, Asian and Middle Easter Studies   , 2, Chinese Studies,                    , 3      , Part IB,                , 4, Modern Chinese texts,             , 1, Lectures,                     3, 17/11,     1, Sue Simpson
 * 1, Asian and Middle Easter Studies   , 2, Chinese Studies,                    , 3      , Part IB,                , 4, Modern Chinese texts,             , 1, Lectures,                     4, 24/11,     1, Sue Simpson
 * 1, Asian and Middle Easter Studies   , 2, Chinese Studies,                    , 3      , Part IB,                , 4, Modern Chinese texts,             , 2, Practicals,                   5, 04/11,     2, Mr Jack McJackerson
 * 1, Asian and Middle Easter Studies   , 2, Chinese Studies,                    , 3      , Part IB,                , 4, Modern Chinese texts,             , 2, Practicals,                   6, 04/11,     3, Dr Jill Jameson
 * 1, Asian and Middle Easter Studies   , 2, Chinese Studies,                    , 3      , Part IB,                , 4, Modern Chinese texts,             , 2, Practicals,                   7, 11/11,     2, Mr Jack McJackerson
 * 1, Asian and Middle Easter Studies   , 2, Chinese Studies,                    , 3      , Part IB,                , 4, Modern Chinese texts,             , 2, Practicals,                   8, 11/11,     3, Dr Jill Jameson
 * 1, Asian and Middle Easter Studies   , 2, Chinese Studies,                    , 3      , Part IB,                , 5, Literary Chinese,                 , 3, Classic of Poetry,            9, 05/11,     1, Sue Simpson
 * 1, Asian and Middle Easter Studies   , 2, Chinese Studies,                    , 4      , Part II,                , 6, China and Warfare,                , 4, Tang dynasty,                 10, 12/11,    4, Dr Wing Lu
 * 1, Asian and Middle Easter Studies   , 2, Chinese Studies,                    , 4      , Part II,                , 6, China and Warfare,                , 4, Tang dynasty,                 11, 19/11,    4, Dr Wing Lu
 * ```
 *
 * As a second example, the "China and Warfare" module will be exported. It's important to remember
 * that the node and what's *under* it will be exported. This means that the course, subject and
 * part will *NOT* be included in the export:
 *
 * ```
 * module_0_id, module_0_displayName, .., series_id, series_displayName, .., event_id, event_displayName, .., organiser_id, organiser_displayName
 * 6, China and Warfare,                , 4, Tang dynasty,                    10, 12/11,                        4, Dr Wing Lu
 * 6, China and Warfare,                , 4, Tang dynasty,                    11, 19/11,                        4, Dr Wing Lu
 * ```
 *
 * As the last example, the input tree will be changed. In the previous examples the input tree was
 * nicely structured with series and events always at the bottom. This doesn't necessarily have to be
 * the case. Series and events can be attached to any organisational unit
 *
 * ```
 * - Engineering department (orgunit:department)
 *   - Civil engineering (orgunit:category)
 *     - Bridge construction (series)
 *       - Suspension on 04/08 (event)
 *       - Pillars on 11/08 (event)
 *   - Fire drills (series)
 *     - March on 01/03 (event)
 *     - April on 01/04 (event)
 *   - Mandatory health and safety session on 06/06 (event)
 * ```
 *
 * This would be exported as:
 *
 * ```
 * department_0_id, department_0_displayName, .., category_1_id, category_1_displayName, .., series_id, series_displayName, .., event_id, event_displayName
 * 1, Engineering department,                   , 2,  Civil engineering,                   , 3,  Bridge construction,         ,  1, Suspension
 * 1, Engineering department,                   , 2,  Civil engineering,                   , 3,  Bridge construction,         ,  2, Pillars
 * 1, Engineering department,                   ,  ,                                       , 3,  Fire drills,                 ,  3, March
 * 1, Engineering department,                   ,  ,                                       , 3,  Fire drills,                 ,  4, April
 * 1, Engineering department,                   ,  ,                                       ,  ,             ,                 ,  5, Mandatory health and safety session
 * ```
 *
 * @Server      admin,app
 * @Method      GET
 * @Path        /orgunit/{id}/export
 * @PathParam   {number}            id              The id of the organisational unit to export
 * @FormParam   {string}            [format]        The format in which the organisational units, event series and events should be exported. Defaults to `json`       [csv,json]
 * @Return      {string|object}                     The exported organisational units, event series and events in either CSV or JSON
 */
var _exportOrgUnit = function(req, res) {
    OrgUnitAPI.exportOrgUnit(req.ctx, req.params.id, req.query.format, function(err, data) {
        if (err) {
            return res.status(err.code).send(err.msg);
        }

        if (req.query.format === 'csv') {
            res.set('Content-Type', 'text/csv');
        }

        return res.status(200).send(data);
    });
};

GrassHopper.globalAdminRouter.on('get', '/api/orgunit/:id/export', _exportOrgUnit);
GrassHopper.appRouter.on('get', '/api/orgunit/:id/export', _exportOrgUnit);

/**
 * @REST importOrgUnit
 *
 * Import a set of given organisational units, event series and events into an organisational unit
 *
 * @Server      admin,app
 * @Method      POST
 * @Path        /orgunit/{id}/import
 * @PathParam   {number}            id              The id of the organisational unit into which to import the data
 * @FormParam   {string}            data            The organisational units, event series and events to import
 * @FormParam   {boolean}           deleteMissing   Whether to delete items from the database that aren't in the import data
 */
var _importOrgUnit = function(req, res) {
    var options = _.pick(req.body, 'deleteMissing');
    OrgUnitImport.importOrgUnit(req.ctx, req.params.id, req.body.data, options, function(errors) {
        if (errors) {
            // Because of the large potential of validation errors, the import API returns everything
            // that is wrong with the provided data
            if (_.isArray(errors)) {
                if (errors.length === 1) {
                    return res.status(errors[0].code).send(errors[0].msg);
                } else {
                    var body = _.pluck(errors, 'msg').join('\n');
                    return res.status(400).send(body);
                }

            // A regular error object was returned
            } else {
                return res.status(errors.code).send(errors.msg);
            }
        }

        return res.sendStatus(200);
    });
};

GrassHopper.globalAdminRouter.on('post', '/api/orgunit/:id/import', _importOrgUnit);
GrassHopper.appRouter.on('post', '/api/orgunit/:id/import', _importOrgUnit);
