// -------------------------------
// Define REST models
//
archDB.factory('TimeLog', ['apiUrl', '$resource', 'ResourceMethods', 'ResourcePrototype', function (apiUrl, $resource, methods, _prototype) {
    var TimeLog = $resource(apiUrl('hr/time-log/:timeLogId'), { timeLogId: '@id' }, methods);
    angular.extend(TimeLog.prototype, _prototype);
    return TimeLog;
}]);

archDB.factory('AdminTimeLog', ['apiUrl', '$resource', 'ResourceMethods', 'ResourcePrototype', function (apiUrl, $resource, methods, _prototype) {
    var AdminTimeLog = $resource(apiUrl('hr/admin/time-log/:timeLogId'), { timeLogId: '@id' }, methods);
    angular.extend(AdminTimeLog.prototype, _prototype);
    return AdminTimeLog;
}]);

archDB.factory('TimeLogChangeRequest', ['apiUrl', '$resource', 'ResourceMethods', 'ResourcePrototype', function (apiUrl, $resource, methods, _prototype) {
    var TimeLogChangeRequest = $resource(apiUrl('hr/time-log-change-requests/:timeLogChangeRequestId'), { timeLogChangeRequestId: '@id' }, methods);
    angular.extend(TimeLogChangeRequest.prototype, _prototype);
    return TimeLogChangeRequest;
}]);

archDB.factory('UserDetails', ['apiUrl', '$resource', 'ResourceMethods', 'ResourcePrototype', function (apiUrl, $resource, methods, _prototype) {
    var UserDetails = $resource(apiUrl('hr/user-details/:userId'), { userId: '@user_id' }, methods);
    angular.extend(UserDetails.prototype, _prototype);
    return UserDetails;
}]);

archDB.factory('Holiday', ['apiUrl', '$resource', 'ResourceMethods', 'ResourcePrototype', function (apiUrl, $resource, methods, _prototype) {
    var Holiday = $resource(apiUrl('hr/holiday/:holidayId'), { holidayId: '@id' }, methods);
    angular.extend(Holiday.prototype, _prototype);
    return Holiday;
}]);
archDB.directive("clockInOut", function () {
    return {
        restrict: "A",
        scope: true,
        controller: [
            "$scope",
            "ClockingStatusService",
            "Messenger",
            "TimeLog",
            "ErrorsHandler",
            function ($scope, Status, Messenger, TimeLog, ErrorsHandler) {
                $scope.getText = function () {
                    if (Status.isClockedIn() || Status.isAtLunch()) {
                        return "Clock Out";
                    }
                    if (Status.isClockedOut()) {
                        return "Clock In";
                    }
                    return "Clock In";
                };

                $scope.getIcon = function () {
                    if (Status.isClockedIn() || Status.isAtLunch()) {
                        return "fa fa-circle fa-fw text-danger";
                    }
                    if (Status.isClockedOut()) {
                        return "fa fa-circle fa-fw text-success";
                    }
                    return "fa fa-circle fa-fw text-success";
                };

                $scope.action = function () {
                    var type = "in";
                    if (Status.isClockedIn() || Status.isAtLunch()) {
                        type = "Out";
                    } else if (Status.isClockedOut()) {
                        type = "in";
                    }

                    TimeLog.save(
                        { type: type },
                        function (response) {
                            Status.setStatus(response);
                            Messenger("You have been clocked " + type);
                        },
                        ErrorsHandler
                    );
                };
            }
        ],
        replace: true,
        template:
            '<li><a href="#" ng-click="action()" eat-click><i ng-class="getIcon()"></i> {[{ getText() }]}</a></li>'
    };
});

archDB.directive("clockingStatus", function () {
    return {
        restrict: "A",
        controller: [
            "$scope",
            "ClockingStatusService",
            "TimeLog",
            "ErrorsHandler",
            function ($scope, Status, TimeLog, ErrorsHandler) {
                const actions = {
                    clockIn: {
                        label: "Clock In",
                        action: function () {
                            return TimeLog.save(
                                { type: "in" },
                                function (response) {
                                    Status.setStatus(response);

                                    alert.update({
                                        message: "You are now clocked in :)",
                                        type: "success",
                                        actions: false,
                                        hideAfter: 3
                                    });
                                },
                                ErrorsHandler
                            );
                        }
                    },
                    clockInLunch: {
                        label: "Clock In from Lunch",
                        action: function () {
                            return TimeLog.save(
                                { type: "in", lunch: true },
                                function (response) {
                                    Status.setStatus(response);

                                    alert.update({
                                        message: "You are now clocked in from lunch :)",
                                        type: "success",
                                        actions: false,
                                        hideAfter: 3
                                    });
                                },
                                ErrorsHandler
                            );
                        }
                    }
                };
                // We will expose the Service method to this controller
                $scope.status = Status;

                // Define Messenger options
                Messenger.options = {
                    extraClasses: "messenger-fixed messenger-on-top messenger-on-right",
                    theme: "future"
                };

                // If the user is not clocked in then we will display an alert
                // with a clocking button so he can easily clock in

                var alert;

                var AlertCallback = function () {
                    console.log("AlertCallback", Status.isAtLunch());

                    if ((Status.isClockedOut() || Status.isAtLunch()) && Status.ready) {
                        if (alert && alert.shown === true) {
                            return false;
                        }

                        let message = "You are not clocked in.";
                        action = actions.clockIn;
                        if (Status.isAtLunch()) {
                            message = "You are at lunch.";
                            action = actions.clockInLunch;
                        }

                        // We are not currently clocked in...
                        // so we will display the alert
                        alert = Messenger().post({
                            message,
                            type: "error",
                            showCloseButton: true,
                            hideAfter: 0,
                            actions: {
                                action
                            }
                        });
                    }
                };

                $scope.$watch("status.ready", AlertCallback);
                $scope.$watch("status.status", AlertCallback);
            }
        ],
        template:
            '<small><i ng-class="{\'fa fa-circle text-success\': status.isClockedIn() && !status.isAtLunch(), \'fa fa-circle text-lunch\': status.isAtLunch(), \'fa fa-circle text-danger\': !status.isClockedIn() && !status.isAtLunch()}"></i></small> <span ng-show="status.isClockedIn() && !status.isAtLunch()">Clocked In</span> <span ng-show="status.isAtLunch()">On Lunch</span> <span ng-show="!status.isClockedIn() && !status.isAtLunch()">Clocked Out</span>'
    };
});

archDB.directive("lunch", function () {
    return {
        restrict: "A",
        scope: true,
        controller: [
            "$scope",
            "ClockingStatusService",
            "Messenger",
            "TimeLog",
            "ErrorsHandler",
            function ($scope, Status, Messenger, TimeLog, ErrorsHandler) {
                $scope.getText = function () {
                    if (Status.isAtLunch()) {
                        return "Clock In from lunch.";
                    }
                    return "Clock Out for lunch";
                };
                $scope.toShow = function () {
                    return Status.isClockedIn() || Status.isAtLunch();
                };
                $scope.getIcon = function () {
                    if (Status.isAtLunch()) {
                        return "fa fa-cutlery fa-fw text-success";
                    }
                    return "fa fa-cutlery fa-fw text-danger";
                };

                $scope.action = function () {
                    var type = "out";
                    var lunch = true;
                    if (Status.isAtLunch()) {
                        type = "in";
                    }

                    TimeLog.save(
                        { type: type, lunch: lunch },
                        function (response) {
                            Status.setStatus(response);
                            Messenger("You have been clocked " + type + " from lunch");
                        },
                        ErrorsHandler
                    );
                };
            }
        ],
        replace: true,
        template:
            '<li ng-show="toShow()"><a href="#" ng-click="action()" eat-click><i ng-class="getIcon()"></i> {[{ getText() }]}</a></li>'
    };
});

archDB.controller('ApproveDeclineTimeModalCtrl', ['$scope', '$uibModalInstance', 'TimeLogChangeRequest', 'ErrorsHandler', 'options', 'DateTime', function ($scope, $uibModalInstance, TimeLogChangeRequest, ErrorsHandler, options, DateTime) {

    var time = moment(options.log.time);
    $scope.DateTime = DateTime;

    $scope.data = {
        id: options.log.id
    };

    $scope.current_date = time.format('DD MMM YYYY - HH:mm');
    $scope.selected_date = {
        hour: time.format('HH'),
        minute: time.format('mm'),
        day: time.format('DD'),
        month: time.format('MM'),
        year: time.format('YYYY')
    };

    var TimeChanged = function () {
        $scope.data.time = moment({
            year: parseInt($scope.selected_date.year, 10),
            month: parseInt($scope.selected_date.month, 10) - 1,
            day: parseInt($scope.selected_date.day, 10),
            hour: parseInt($scope.selected_date.hour, 10),
            minute: parseInt($scope.selected_date.minute, 10)
        }).format("YYYY-MM-DD HH:mm:ss");
    };

    // Watch for changes
    $scope.$watch('selected_date', TimeChanged, true);

    $scope.approve = function () {
        $scope.data.completed = 1;
        TimeLogChangeRequest.update($scope.data, function (response) {
            $uibModalInstance.close(response);
        }, ErrorsHandler);
    };

    $scope.decline = function () {
        $scope.data.declined = 1;
        TimeLogChangeRequest.update($scope.data, function (response) {
            $uibModalInstance.close(response);
        }, ErrorsHandler);
    };

    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };
}]);
archDB.controller('EditUserAddressCtrl', ['$scope', '$uibModalInstance', 'options', 'UserDetails', 'ErrorsHandler', function ($scope, $uibModalInstance, options, UserDetails, ErrorsHandler) {

    $scope.data = options.user;

    $scope.submit = function () {
        UserDetails.update($scope.data, function (response) {
            $uibModalInstance.close(response);
        }, ErrorsHandler);
    };

    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };

}]);
archDB.controller('HolidayRequestModalCtrl', ['$scope', 'DateTime', '$uibModalInstance', 'Holiday', 'ErrorsHandler', 'Messenger', 'user_details', function ($scope, DateTime, $uibModalInstance, Holiday, ErrorsHandler, Messenger, user_details) {

    // Initialize scope variables
    $scope.DateTime = DateTime;
    $scope.user_details = user_details;
    $scope.from = angular.copy(DateTime.defaults);
    $scope.to = angular.copy(DateTime.defaults);
    $scope.total_holidays = 0;
    
    $scope.data = {
        paid: 1,
        description: ''
    };
    
    // Holiday types removed - using radio buttons now
    
    // Simple HTML5 date inputs - no conflicting calendar libraries
    $scope.fromDateModel = null;
    $scope.toDateModel = null;
    $scope.total_holidays = 0;
    
    // Get today's date in YYYY-MM-DD format for HTML5 date input
    $scope.getTodayDate = function() {
        return moment().format('YYYY-MM-DD');
    };
    
    // Update from date and recalculate
    $scope.updateFromDate = function() {
        if ($scope.fromDateModel) {
            // Handle Date objects from HTML5 input - extract date components to avoid timezone issues
            var fromMoment;
            if ($scope.fromDateModel instanceof Date) {
                // Extract year, month, day from the Date object and create UK timezone moment
                var year = $scope.fromDateModel.getFullYear();
                var month = $scope.fromDateModel.getMonth(); // 0-based
                var day = $scope.fromDateModel.getDate();
                fromMoment = moment.tz([year, month, day], 'Europe/London');
            } else {
                // String input - parse in UK timezone
                fromMoment = moment.tz($scope.fromDateModel, 'YYYY-MM-DD', 'Europe/London');
            }

            $scope.from.days = fromMoment.format('DD');
            $scope.from.months = fromMoment.format('MM');
            $scope.from.years = fromMoment.format('YYYY');
            $scope.data.start_date = fromMoment.format('YYYY-MM-DD 00:00:00');

            // If to date exists and is before from date, clear it
            var toMoment;
            if ($scope.toDateModel instanceof Date) {
                var toYear = $scope.toDateModel.getFullYear();
                var toMonth = $scope.toDateModel.getMonth();
                var toDay = $scope.toDateModel.getDate();
                toMoment = moment.tz([toYear, toMonth, toDay], 'Europe/London');
            } else if ($scope.toDateModel) {
                toMoment = moment.tz($scope.toDateModel, 'YYYY-MM-DD', 'Europe/London');
            }

            if (toMoment && toMoment.isBefore(fromMoment)) {
                $scope.toDateModel = null;
                $scope.data.end_date = null;
            }

            calculateWorkingDays();
        }
    };
    
    // Update to date and recalculate
    $scope.updateToDate = function() {
        if ($scope.toDateModel) {
            // Handle Date objects from HTML5 input - extract date components to avoid timezone issues
            var toMoment;
            if ($scope.toDateModel instanceof Date) {
                // Extract year, month, day from the Date object and create UK timezone moment
                var year = $scope.toDateModel.getFullYear();
                var month = $scope.toDateModel.getMonth(); // 0-based
                var day = $scope.toDateModel.getDate();
                toMoment = moment.tz([year, month, day], 'Europe/London');
            } else {
                // String input - parse in UK timezone
                toMoment = moment.tz($scope.toDateModel, 'YYYY-MM-DD', 'Europe/London');
            }

            $scope.to.days = toMoment.format('DD');
            $scope.to.months = toMoment.format('MM');
            $scope.to.years = toMoment.format('YYYY');
            $scope.data.end_date = toMoment.format('YYYY-MM-DD 00:00:00');

            calculateWorkingDays();
        }
    };
    
    // Clear all dates
    $scope.clearDates = function() {
        $scope.fromDateModel = null;
        $scope.toDateModel = null;
        $scope.data.start_date = null;
        $scope.data.end_date = null;
        $scope.total_holidays = 0;
        
        // Reset hidden fields
        $scope.from = angular.copy(DateTime.defaults);
        $scope.to = angular.copy(DateTime.defaults);
    };
    
    // Calculate working days (Monday to Friday) - using UK server timezone
    function calculateWorkingDays() {
        if (!$scope.fromDateModel || !$scope.toDateModel) {
            $scope.total_holidays = 0;
            return;
        }

        // Parse dates in UK timezone to avoid browser timezone shifting
        var startDate, endDate;

        if ($scope.fromDateModel instanceof Date) {
            // Extract the local date components and create UK timezone moment
            var fromYear = $scope.fromDateModel.getFullYear();
            var fromMonth = $scope.fromDateModel.getMonth(); // 0-based
            var fromDay = $scope.fromDateModel.getDate();
            startDate = moment.tz([fromYear, fromMonth, fromDay], 'Europe/London');
        } else {
            // Parse string date in UK timezone
            startDate = moment.tz($scope.fromDateModel, 'YYYY-MM-DD', 'Europe/London');
        }

        if ($scope.toDateModel instanceof Date) {
            // Extract the local date components and create UK timezone moment
            var toYear = $scope.toDateModel.getFullYear();
            var toMonth = $scope.toDateModel.getMonth(); // 0-based
            var toDay = $scope.toDateModel.getDate();
            endDate = moment.tz([toYear, toMonth, toDay], 'Europe/London');
        } else {
            // Parse string date in UK timezone
            endDate = moment.tz($scope.toDateModel, 'YYYY-MM-DD', 'Europe/London');
        }

        // Calculate the difference in days using production logic
        var counter = endDate.diff(startDate, 'days') + 1;
        var start = startDate.clone();
        var totalHols = 0;

        for (var i = 0; i < counter; i++) {
            var day = start.isoWeekday();

            // Exclude Saturday (6) and Sunday (7) - same as production
            if (day !== 6 && day !== 7) {
                totalHols++;
            }

            start.add(1, 'days');
        }
        $scope.total_holidays = totalHols;
    }
    
    // Get formatted date range for display
    $scope.getSelectedDateRange = function() {
        if (!$scope.fromDateModel || !$scope.toDateModel) {
            return '';
        }
        
        var start = moment($scope.fromDateModel).format('DD MMM YYYY');
        var end = moment($scope.toDateModel).format('DD MMM YYYY');
        
        if (start === end) {
            return start;
        }
        
        return start + ' - ' + end;
    };
    
    // Get selected holiday type info - removed since using radio buttons


    // Functions below
    $scope.save = function () {
        Holiday.save($scope.data, function (response) {
            $uibModalInstance.close(response);
            Messenger("Your holiday request was successfully saved.");
        }, ErrorsHandler);
    };

    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };



}]);

archDB.controller('LogTimeRequestChangeCtrl', ['$scope', '$uibModalInstance', 'TimeLogChangeRequest', 'AdminTimeLog', 'ErrorsHandler', 'options', 'DateTime', function ($scope, $uibModalInstance, TimeLogChangeRequest, AdminTimeLog, ErrorsHandler, options, DateTime) {

    var time = moment(options.log.time);

    $scope.DateTime = DateTime;

    $scope.data = {
        time_log_id: options.log.id
    };

    $scope.current_date = time.format('DD MMM YYYY - HH:mm');
    $scope.selected_date = {
        hour: time.format('HH'),
        minute: time.format('mm'),
        day: time.format('DD'),
        month: time.format('MM'),
        year: time.format('YYYY')
    };

    var TimeChanged = function () {
        $scope.data.time = moment({
            year: parseInt($scope.selected_date.year, 10),
            month: parseInt($scope.selected_date.month, 10) - 1,
            day: parseInt($scope.selected_date.day, 10),
            hour: parseInt($scope.selected_date.hour, 10),
            minute: parseInt($scope.selected_date.minute, 10)
        }).format("YYYY-MM-DD HH:mm:ss");
    };

    // Watch for changes
    $scope.$watch('selected_date', TimeChanged, true);

    $scope.save = function () {

        if (options.admin) {
            $scope.data.id = options.log.id;
            AdminTimeLog.update($scope.data, function (response) {
                $uibModalInstance.close(response);
            }, ErrorsHandler);
        }
        else {
            TimeLogChangeRequest.save($scope.data, function (response) {
                $uibModalInstance.close(response);
            }, ErrorsHandler);
        }

    };

    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };

}]);
archDB.controller('NewRecordRequestCtrl', ['$scope', '$uibModalInstance', 'TimeLog', 'AdminTimeLog', 'ErrorsHandler', 'options', 'DateTime', function ($scope, $uibModalInstance, TimeLog, AdminTimeLog, ErrorsHandler, options, DateTime) {

    var time = moment(options.date),
        i, formatted;

    $scope.DateTime = DateTime;

    $scope.data = {
        type: options.type,
        new_record_request: true,
        user_id: options.user.user_id
    };

    $scope.selected_date = {
        hour: (options.type == 'in') ? options.user.default_start_time.split(':')[0] : options.user.default_end_time.split(':')[0],
        minute: (options.type == 'in') ? options.user.default_start_time.split(':')[1] : options.user.default_end_time.split(':')[1],
        day: time.format('DD'),
        month: time.format('MM'),
        year: time.format('YYYY')
    };

    var TimeChanged = function () {
        $scope.data.time = moment({
            year: parseInt($scope.selected_date.year, 10),
            month: parseInt($scope.selected_date.month, 10) - 1,
            day: parseInt($scope.selected_date.day, 10),
            hour: parseInt($scope.selected_date.hour, 10),
            minute: parseInt($scope.selected_date.minute, 10)
        }).format("YYYY-MM-DD HH:mm:ss");
    };

    // Watch for changes
    $scope.$watch('selected_date', TimeChanged, true);

    $scope.save = function () {

        var model = options.admin ? AdminTimeLog : TimeLog;

        model.save($scope.data, function (response) {
            $uibModalInstance.close(response);
        }, ErrorsHandler);

    };

    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };

}]);
archDB.service('$ClockingLogs', function () {

    // Little helper
    var self = this;

    /**
     * This is a sum of the total hours. It is calculated during the
     * sorting of the results.
     *
     * @type Float
     */
    self.total_hours = 0;

    self.daterangepicker = {
        ranges: {
            'This Month': [moment().subtract('month', 1).set('date', 29).hours(0).minutes(0).seconds(0), moment().set('date', 28).hours(23).minutes(59).seconds(59)],
            'Last Month': [moment().subtract('month', 2).set('date', 28).hours(0).minutes(0).seconds(0), moment().subtract('month', 1).set('date', 27).hours(23).minutes(59).seconds(59)],
        },
        locale: {
            firstDay: 1 // Monday is the first day of the week
        }
    };

    self.selected_period = {
        startDate: self.daterangepicker.ranges['This Month'][0],
        endDate: self.daterangepicker.ranges['This Month'][1]
    };

    /**
     * This function takes the response received from the server and
     * groups all the times by day and then by groups of two (in & out).
     * It then returns an array of formatted values.
     *
     * @param  array data
     * @return array
     */
    self.prepareData = function (data) {
        var preparedData = {};
        var lastElement;

        // We reset the value of total hours as we are calculating it here...
        self.total_hours = 0;

        _.each(data, function (el) {

            el.time = moment(el.time);
            var date = el.time.format('YYYY-MM-DD');

            // A sample of the output
            // Object = {
            // 		'2014-01-01': [
            // 			{
            // 				in: {object from DB}
            // 				out: {object form DB},
            // 				hours: 2.23 (the difference of the two above)
            // 			}
            // 		]
            // }

            // As seen above we are grouping all the objects by the date
            // excluding the time. Next we are creating groups of 2 (in & out)
            // Here we are checking to see if there is a group for the current element's date
            // if so we will then proceed inside this group
            if (preparedData.hasOwnProperty(date)) {

                // Check to see the last pair that was added
                var lastDate = preparedData[date];

                // We are checking to see if we can create a group of 2
                // basically we are checking to see if the last group in the array has 2 elements
                // if it doesn't then we are adding this as a second element
                // else we will create a new group and add this element as the group's first element.
                var lastGroupItem = lastDate[lastDate.length - 1];

                if (!lastGroupItem[el.type]) {
                    lastGroupItem[el.type] = el;

                    // Calculate hours as this will be the second element
                    // Also we need to figure out the key of the previous element
                    // so if this element is 'in' the other is 'out' or the other way around...
                    var otherIndex = el.type == 'in' ? 'out' : 'in';
                    var hours = moment(el.time).diff(lastGroupItem[otherIndex].time, 'hours', true).toFixed(2)
                    lastGroupItem['hours'] = parseFloat(hours);

                    // add the hours to the total hours
                    if (hours) self.total_hours += parseFloat(hours);

                }
                else {
                    preparedData[date].push({
                        'in': el.type == 'in' ? el : null,
                        'out': el.type == 'out' ? el : null
                    });
                }
            }

            // We need to create a new group for this date
            else {
                preparedData[date] = [{
                    'in': el.type == 'in' ? el : null,
                    'out': el.type == 'out' ? el : null
                }];
            }

        });

        // We now need to add the missing dates from the month interval
        var date = self.selected_period.startDate.clone(),
            endDate = self.selected_period.endDate.clone();

        // Also we will make sure not to go beyond today's date
        while (endDate.isAfter(date)) {
            if (!preparedData.hasOwnProperty(date.format('YYYY-MM-DD'))) {
                preparedData[date.format('YYYY-MM-DD')] = [{
                    'in': null,
                    'out': null
                }];
            }

            date.add('days', 1);
        }

        return preparedData;
    };

});
archDB.service("ClockingStatusService", [
    "TimeLog",
    "ErrorsHandler",
    function (TimeLog, ErrorsHandler) {
        // Little helper :)
        var self = this;

        // This is the current state
        // It is the latest time log in the database
        // @var object
        self.status = null;

        // Determines if the service is fully loaded
        self.ready = false;

        // When the service is initialised we would like
        // to fetch the latest status
        TimeLog.get(
            { lastRecord: true },
            function (response) {
                if (response.id) self.status = response;
                self.ready = true;
            },
            ErrorsHandler
        );

        // -----------------------------------
        // Below are a list of available methods
        //

        self.setStatus = function (value) {
            self.status = value;
        };

        self.getStatus = function () {
            return self.status;
        };

        self.hasStatus = function () {
            return self.status ? true : false;
        };

        self.isClockedIn = function () {
            if (!self.status) {
                return false;
            }
            return self.status && self.status.type == "in" && !self.status.lunch;
        };

        self.isClockedOut = function () {
            if (!self.status) {
                return true;
            }
            return self.status && self.status.type == "out" && !self.status.lunch;
        };
        self.isAtLunch = function () {
            console.log("AlertCallback", self.status);

            if (!self.status) {
                return false;
            }
            return self.status && self.status.lunch == 1;
        };
    }
]);

archDB.service('DateTime', function () {

    // Little helper :)
    var self = this,
        formatted,
        i,
        date = moment();

    self.defaults = {
        days: date.format('DD'),
        months: date.format('MM'),
        years: date.format('YYYY'),
        hours: date.format('HH'),
        minutes: date.format('mm'),
        seconds: date.format('ss')
    };

    self.hours = [];
    self.minutes = [];
    self.days = [];
    self.months = [{ name: 'January', value: '01' }, { name: 'February', value: '02' }, { name: 'March', value: '03' }, { name: 'April', value: '04' }, { name: 'May', value: '05' }, { name: 'June', value: '06' }, { name: 'July', value: '07' }, { name: 'August', value: '08' }, { name: 'September', value: '09' }, { name: 'October', value: '10' }, { name: 'November', value: '11' }, { name: 'December', value: '12' }];
    self.years = [];

    // Generate the drop down selection
    for (i = 0; i < 24; i++) {
        formatted = i < 10 ? '0' + i : '' + i;
        self.hours.push(formatted);
    }

    for (i = 0; i < 60; i++) {
        formatted = i < 10 ? '0' + i : '' + i;
        self.minutes.push(formatted);
    }

    for (i = 1; i < 32; i++) {
        formatted = i < 10 ? '0' + i : '' + i;
        self.days.push(formatted);
    }

    // Years range from current year (2025) to 2030
    for (i = 2025; i <= 2030; i++) {
        formatted = '' + i;
        self.years.push(formatted);
    }

});
archDB.controller("ClockingLogsCtrl", [
    "$scope",
    "TimeLog",
    "ErrorsHandler",
    "$uibModal",
    "$ClockingLogs",
    function ($scope, TimeLog, ErrorsHandler, $uibModal, $ClockingLogs) {
        $scope.service = $ClockingLogs;

        /**
         * Simple watcher that gets triggered when the scope is fully initialised and it will
         * load all the clocking logs.
         *
         * @return null
         */
        $scope.$watch("service.selected_period", function (value) {
            if (value) {
                $scope.load();
            }
        });

        /**
         * This function loads all the clocking logs for the given month. If no month is specified
         * then it returns the current month.
         *
         * @return null
         */
        $scope.load = function () {
            TimeLog.get(
                {
                    startDate: $ClockingLogs.selected_period.startDate
                        .hours(0)
                        .minutes(0)
                        .seconds(0)
                        .format("X"),
                    endDate: $ClockingLogs.selected_period.endDate
                        .hours(23)
                        .minutes(59)
                        .seconds(59)
                        .format("X")
                },
                function (response) {
                    $scope.data = $ClockingLogs.prepareData(response.data);
                    $scope.days = $scope.calDays($scope.data);
                    $scope.count = 10;
                    $scope.show = {};
                    $scope.show[new Date().toISOString().substr(0, 10)] = true;
                },
                ErrorsHandler
            );
        };

        $scope.keys = function (data) {
            return data ? Object.keys(data).sort() : [];
        };
        $scope.calDays = function (data) {
            output = {};
            Object.keys(data).forEach(key => {
                el = data[key];
                el.forEach(obj => {
                    output[key] = output[key] || 0;
                    if (obj.hours) {
                        output[key] += obj.hours;
                    }
                    output[key] = Math.round(output[key] * 100) / 100;
                });
            });
            return output;
        };
        $scope.requestChange = function (log) {
            var modalInstance = $uibModal.open({
                templateUrl: "hr/modals/request_change.html",
                controller: "LogTimeRequestChangeCtrl",
                resolve: {
                    options: function () {
                        return {
                            admin: false,
                            log: log
                        };
                    }
                }
            });

            modalInstance.result.then(function (response) {
                log.pending_change_requests.push(response);
            });
        };

        $scope.newRecord = function (date, type) {
            var modalInstance = $uibModal.open({
                templateUrl: "hr/modals/new_record_request.html",
                controller: "NewRecordRequestCtrl",
                resolve: {
                    options: function () {
                        return {
                            admin: false,
                            date: date ? date : new Date(),
                            type: type ? type : "in",
                            user: $scope.user_details
                        };
                    }
                }
            });

            modalInstance.result.then(function (response) {
                $scope.load();
            });
        };

        $scope.generateTimesheet = function () {
            var modalInstance = $uibModal.open({
                templateUrl: "hr/modals/generate_individual_timesheet.html",
                controller: "HrGenerateTimesheetCtrl",
                scope: $scope
            });
        };
    }
]);

archDB.controller("HolidayRequestsCtrl", [
    "$scope",
    "Holiday",
    "ErrorsHandler",
    "$uibModal",
    function ($scope, Holiday, ErrorsHandler, $uibModal) {
        $scope.load = function () {
            Holiday.get(
                { own: true },
                function (response) {
                    $scope.requests = response.data;
                },
                ErrorsHandler
            );
        };

        $scope.load();

        $scope.requestHoliday = function () {
            var modalInstance = $uibModal.open({
                templateUrl: "hr/modals/holiday_request.html",
                controller: "HolidayRequestModalCtrl",
                size: "lg",
                resolve: {
                    user_details: function () {
                        return $scope.user_details;
                    }
                }
            });

            modalInstance.result.then(function (holiday) {
                $scope.requests.push(holiday);
            });
        };

        $scope.getStatusClass = function (request) {
            if (!request.hasOwnProperty("status")) return "";

            switch (request.status.toLowerCase()) {
                case "pending":
                    return "label-warning";
                case "approved":
                    return "label-success";
                case "declined":
                    return "label-danger";
                case "cancelled":
                    return "label-warning";
                default:
                    return "";
            }
        };
    }
]);

archDB.controller('AdminHolidayRequestsCtrl', ['$scope', 'Holiday', 'ErrorsHandler', function ($scope, Holiday, ErrorsHandler) {

    $scope.load = function () {
        Holiday.get({ pending: true }, function (response) {
            $scope.holidays = response.data;
        }, ErrorsHandler);
    };

    $scope.approve = function (holiday) {
        Holiday.update({ id: holiday.id, status: 'approved' }, function (response) {
            Messenger("The holiday was approved!");
            $scope.holidays = _.reject($scope.holidays, function (el) { return el.id == holiday.id; });
        }, ErrorsHandler);
    };

    $scope.decline = function (holiday) {
        Holiday.update({ id: holiday.id, status: 'declined' }, function (response) {
            Messenger("The holiday was declined!");
            $scope.holidays = _.reject($scope.holidays, function (el) { return el.id == holiday.id; });
        }, ErrorsHandler);
    };

    $scope.load();
}]);
archDB.controller('AdminUserHolidaysCtrl', ['$scope', 'Holiday', 'ErrorsHandler', function ($scope, Holiday, ErrorsHandler) {

    $scope.load = function () {
        Holiday.get({ user_id: $scope.user_details.user_id }, function (response) {
            $scope.holidays = response.data;
        }, ErrorsHandler);
    };

    $scope.approve = function (holiday) {
        Holiday.update({ id: holiday.id, status: 'approved' }, function (response) {
            Messenger("The holiday was approved!");
            angular.extend(holiday, response || {});
        }, ErrorsHandler);
    };

    $scope.decline = function (holiday) {
        Holiday.update({ id: holiday.id, status: 'declined' }, function (response) {
            Messenger("The holiday was declined!");
            angular.extend(holiday, response || {});
        }, ErrorsHandler);
    };

    $scope.load();
}]);
archDB.controller("AdminUserTimeClockCtrl", [
    "$scope",
    "AdminTimeLog",
    "ErrorsHandler",
    "$uibModal",
    "$ClockingLogs",
    "$q",
    "UserDetails",
    "Holiday",
    "Messenger",
    function (
        $scope,
        AdminTimeLog,
        ErrorsHandler,
        $uibModal,
        $ClockingLogs,
        $q,
        UserDetails,
        Holiday,
        Messenger
    ) {
        /**
         * Data shared between user view & admin view
         *
         * @type Object
         */
        $scope.service = $ClockingLogs;

        /**
         * Simple watcher that gets triggered when the scope is fully initialised and it will
         * load all the clocking logs.
         *
         * @return null
         */
        $scope.$watch("service.selected_period", function (value) {
            if (value) {
                $scope.load();
            }
        });

        /**
         * This function loads all the clocking logs for the given month. If no month is specified
         * then it returns the current month.
         *
         * @return null
         */
        $scope.load = function () {
            AdminTimeLog.get(
                {
                    user_id: $scope.user_details.user_id,
                    startDate: $ClockingLogs.selected_period.startDate
                        .hours(0)
                        .minutes(0)
                        .seconds(0)
                        .format("X"),
                    endDate: $ClockingLogs.selected_period.endDate
                        .hours(23)
                        .minutes(59)
                        .seconds(59)
                        .format("X")
                },
                function (response) {
                    $scope.data = $ClockingLogs.prepareData(response.data);
                    $scope.days = $scope.calDays($scope.data);
                    $scope.count = 10;
                    $scope.show = {};
                    $scope.show[new Date().toISOString().substr(0, 10)] = true;
                },
                ErrorsHandler
            );
        };

        $scope.calDays = function (data) {
            output = {};
            Object.keys(data).forEach(key => {
                el = data[key];
                el.forEach(obj => {
                    output[key] = output[key] || 0;
                    if (obj.hours) {
                        output[key] += obj.hours;
                    }
                    output[key] = Math.round(output[key] * 100) / 100;
                });
            });
            return output;
        };

        $scope.keys = function (data) {
            return data ? Object.keys(data).sort() : [];
        };

        $scope.saveUserData = function (name, value) {
            var deferred = $q.defer(),
                data = { user_id: $scope.user_details.user_id };

            data[name] = value;

            UserDetails.update(
                data,
                function (response) {
                    deferred.resolve();
                },
                function (res) {
                    deferred.reject(res.data.error);
                }
            );

            return deferred.promise;
        };

        $scope.requestChange = function (log) {
            var modalInstance = $uibModal.open({
                templateUrl: "hr/modals/request_change.html",
                controller: "LogTimeRequestChangeCtrl",
                resolve: {
                    options: function () {
                        return {
                            admin: true,
                            log: log
                        };
                    }
                }
            });

            modalInstance.result.then(function (response) {
                $scope.load();
            });
        };

        $scope.newRecord = function (date, type) {
            var modalInstance = $uibModal.open({
                templateUrl: "hr/modals/new_record_request.html",
                controller: "NewRecordRequestCtrl",
                resolve: {
                    options: function () {
                        return {
                            admin: true,
                            date: date ? date : new Date(),
                            type: type ? type : "in",
                            user: $scope.user_details
                        };
                    }
                }
            });

            modalInstance.result.then(function (response) {
                $scope.load();
            });
        };

        $scope.showApproveDeclineModal = function (log) {
            var modalInstance = $uibModal.open({
                templateUrl: "hr/modals/approve-decline-time.html",
                controller: "ApproveDeclineTimeModalCtrl",
                resolve: {
                    options: function () {
                        return {
                            log: log
                        };
                    }
                }
            });

            modalInstance.result.then(function (response) {
                $scope.load();
            });
        };

        $scope.editAddress = function () {
            var modalInstance = $uibModal.open({
                templateUrl: "hr/modals/user-address.html",
                controller: "EditUserAddressCtrl",
                resolve: {
                    options: function () {
                        return {
                            user: $scope.user_details
                        };
                    }
                }
            });

            modalInstance.result.then(function (response) {
                angular.extend($scope.user_details, response || {});
            });
        };

        $scope.cancelHoliday = function (holiday) {
            Holiday.update(
                { id: holiday.id, status: "cancelled" },
                function (response) {
                    Messenger("The holiday was cancelled!");
                    angular.extend(holiday, response || {});
                },
                ErrorsHandler
            );
        };
    }
]);

archDB.controller('HolidaysCalendarCtrl', ['$scope', 'Holiday', 'ErrorsHandler', function ($scope, Holiday, ErrorsHandler) {

    var EventsLoaded = false;

    $scope.eventSources = [
        {
            events: function (start, end, callback) {
                $scope.loadCalendarEvents(Math.round(start.getTime() / 1000), Math.round(end.getTime() / 1000), callback);
                if (EventsLoaded) {
                    $scope.$apply();
                }
                EventsLoaded = true;
            },
            editable: false
        }
    ];

    $scope.calendar = {
        editable: false,
        defaultView: 'month',
        firstDay: 1,
        axisFormat: 'HH:mm',
        timeFormat: {
            agenda: 'HH:mm{ - HH:mm}'
        },
        header: {
            left: 'prev, next',
            center: 'title',
            right: 'today'
        }
    };

    $scope.loadCalendarEvents = function (start, end, callback) {
        Holiday.get({ startDate: start, endDate: end, status: 'approved' }, function (response) {
            callback(response.data);
        }, ErrorsHandler);
    };

}]);
archDB.controller('HrGenerateTimesheetCtrl', ['$scope', '$uibModalInstance', '$ClockingLogs', '$http', function ($scope, $uibModalInstance, $ClockingLogs, $http) {

    $scope.service = $ClockingLogs;

    $scope.data = {
        send_email: '0',
        download: '1'
    };

    /** this was added by nadeed 25.4.17
    * it allows the reuse of this function by ClockingsLogsCtrl
    *
    * the scope variable from that page is paased into this controller
    * it is then available as $scope.$parent.$parent
    */
    if ($scope.$parent.$parent) {
        $scope.user = $scope.$parent.$parent.user_details.user;
    }

    $scope.$watch('service.selected_period', function (value) {
        if (value) {
            // Use format() instead of toISOString() to avoid timezone conversion issues
            $scope.data.start = $ClockingLogs.selected_period.startDate.hours(0).minutes(0).seconds(0).format('YYYY-MM-DD HH:mm:ss');
            $scope.data.end = $ClockingLogs.selected_period.endDate.hours(23).minutes(59).seconds(59).format('YYYY-MM-DD HH:mm:ss');
        }
    });

    $scope.submit = function () {
        $scope.loading = true;

        // this section sends the user to a different route depending on whch page they're on
        // this is for the user clocking-times page
        if ($scope.hasOwnProperty('user')) {
            $http.post('/hr/admin/user/' + $scope.user.id + '/report', $scope.data)
                .success(function (response) {
                    $scope.loading = false;
                    $scope.error = false;
                    $scope.response = response;
                })
                .error(function () {
                    $scope.error = true;
                    $scope.loading = false;
                    $scope.response = null;
                });
        }
        else {
            // this is for the hr timesheet page
            $http.post('/hr/admin/users/report', $scope.data)
                .success(function (response) {
                    $scope.loading = false;
                    $scope.error = false;
                    $scope.response = response;
                })
                .error(function () {
                    $scope.error = true;
                    $scope.loading = false;
                    $scope.response = null;
                });
        }
    };

    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };

}]);
archDB.controller('HrUsersCtrl', ['$scope', 'UserDetails', 'ErrorsHandler', '$uibModal', function ($scope, UserDetails, ErrorsHandler, $uibModal) {

    $scope.load = function () {
        UserDetails.get(function (response) {
            if (response.reload == true) {
                $scope.load();
            }
            else {
                $scope.users = response.data;
            }
        }, ErrorsHandler);
    };

    $scope.runningCosts = function () {
        var total = 0;

        _.each($scope.users, function (el) {
            if (el.latest_time_log && el.latest_time_log.type == 'in') {
                total += parseFloat(el.rate_per_hour);
            }
        });

        return total;
    };

    $scope.generateTimesheet = function () {
        var modalInstance = $uibModal.open({
            templateUrl: 'hr/modals/generate_timesheet.html',
            controller: 'HrGenerateTimesheetCtrl'
        });
    };

    $scope.load();

}]);
archDB.controller('TimeLogPendingRequestsCtrl', ['$scope', 'TimeLogChangeRequest', 'ErrorsHandler', 'Messenger', '$uibModal', function ($scope, TimeLogChangeRequest, ErrorsHandler, Messenger, $uibModal) {

    $scope.load = function () {
        TimeLogChangeRequest.get({ open: true }, function (response) {

            // Turn each date into a moment object
            _.each(response.data, function (el) {
                el.time = moment(el.time);
                if (el.time_log) el.time_log.time = moment(el.time_log.time);
            });

            // Now we can assign it to the scope
            $scope.requests = response.data;

        }, ErrorsHandler);
    };

    $scope.edit = function (request) {
        var modalInstance = $uibModal.open({
            templateUrl: 'hr/modals/approve-decline-time.html',
            controller: 'ApproveDeclineTimeModalCtrl',
            resolve: {
                options: function () {
                    return {
                        log: request
                    };
                }
            }
        });

        modalInstance.result.then(function (response) {
            $scope.requests = _.reject($scope.requests, function (el) { return el.id == request.id; });
        });
    };

    $scope.approve = function (request) {
        TimeLogChangeRequest.update({ id: request.id, completed: 1 }, function (response) {
            Messenger("The request was approved!");
            $scope.requests = _.reject($scope.requests, function (el) { return el.id == request.id; });
        }, ErrorsHandler);
    };

    $scope.decline = function (request) {
        TimeLogChangeRequest.update({ id: request.id, declined: 1 }, function (response) {
            Messenger("The request was declined!");
            $scope.requests = _.reject($scope.requests, function (el) { return el.id == request.id; });
        }, ErrorsHandler);
    };

    $scope.load();
}]);
