module.exports = Self => {
    Self.remoteMethod('clone', {
        description: 'Clone zone and all its properties including geolocations',
        accessType: 'WRITE',
        accepts: {
            arg: 'id',
            type: 'number',
            required: true,
            description: 'Zone id',
            http: {source: 'path'}
        },
        returns: {
            root: true,
            type: 'Object'
        },
        http: {
            path: '/:id/clone',
            verb: 'POST'
        }
    });

    Self.clone = async id => {
        const models = Self.app.models;
        const tx = await Self.beginTransaction({});

        try {
            let options = {transaction: tx};

            // Find original zone
            const zone = await models.Zone.findOne({
                fields: [
                    'name',
                    'hour',
                    'warehouseFk',
                    'agencyModeFk',
                    'travelingDays',
                    'price',
                    'bonus',
                    'isVolumetric'],
                where: {id}
            }, options);

            const hour = zone.hour;
            const offset = hour.getTimezoneOffset() * 60000;
            hour.setTime(hour.getTime() + offset);

            // Find all original included geolocations
            const includedGeo = await models.ZoneIncluded.find({
                fields: ['geoFk', 'isIncluded'],
                where: {zoneFk: id}
            }, options);

            // Find all original selected days
            const calendarDays = await models.ZoneCalendar.find({
                where: {zoneFk: id}
            }, options);

            const newZone = await Self.create(zone, options);
            const newIncludedGeo = includedGeo.map(included => {
                included.zoneFk = newZone.id;
                return included;
            });
            const newCalendayDays = calendarDays.map(day => {
                day.zoneFk = newZone.id;
                return day;
            });

            await models.ZoneIncluded.create(newIncludedGeo, options);
            await models.ZoneCalendar.create(newCalendayDays, options);
            await tx.commit();

            return newZone;
        } catch (e) {
            await tx.rollback();
            throw e;
        }
    };
};