angular.module('odoo')

    /**
     *
     */
    .factory('customersRemoteFactory', function (
        customersStorageFactory,
        odooFactory,
        sqlFactory,
        asyncLoopFactory
    ) {

        /**
         *
         */
        var pull = function (id, success, error) {
            if (id) {

                odooFactory.read('res.partner', [['id', '=', id]], function (response) {
                    success(response);
                }, function (odooErr) {
                    error(odooErr);
                });

            } else {

                odooFactory.read('res.partner', [['customer', '=', true]], function (response) {
                    success(response);
                }, function (odooErr) {
                    error(odooErr)
                });

            }
        }

        /**
         *
         */
        var push = function (id, data, success, error) {

            // Avoid odoo server warning message
            delete data.id;
            delete data.remote_id;
            delete data.modified;

            if (id) {

                pull(id, function (response) {
                    if (response.length == 1) {
                        var remoteData = response[0];

                        var remoteDate = new Date(remoteData.__last_update);
                        var localDate = new Date(data.modifiedDate);

                        delete data.modifiedDate;

                        if (localDate > remoteDate) {

                            odooFactory.write('res.partner', id, data, function (response) {
                                success(response);
                            }, function (odooErr) {
                                error(odooErr);
                            });

                        } else {
                            success(response);
                        }

                    } else {
                        success(response);
                    }

                }, function (pullErr) {
                    error(pullErr);
                });

            } else {

                delete data.modifiedDate;

                odooFactory.create('res.partner', data, function (response) {
                    success(response);
                }, function (odooErr) {
                    error(odooErr);
                });

            }
        }

        /**
         *
         */
        var destroy = function (id, success, error) {

            odooFactory.unlink('res.partner', id, function (response) {
                success(response);
            }, function (odooInteroperabilityFactoryErr) {
                error(odooInteroperabilityFactoryErr);
            });
        }

        /**
         *
         */
        var get = function (constraint, success, error) {
            sqlFactory.selectByConstraint('partner', constraint, function (customers) {
                success(customers);
            }, function (err) {
                error(err);
            });
        }


        /**
         *
         */
        var syncNewData = function (success, error) {
            get('remote_id = 0 AND customer = 1', function (newCustomers) {
                asyncLoopFactory(newCustomers.length, function (loop) {
                    var data = newCustomers.item(loop.iteration());

                    push(null, data, function (response) {
                        loop.next();
                    }, function (pushErr) {
                        loop.break();
                    });

                    // end loop
                }, function () {
                    success(newCustomers);
                });
            }, function (getErr) {
                error(getErr);
            });
        }

        /**
         *
         */
        var syncUpdatedData = function (success, error) {
            get('remote_id != 0 AND customer = 1 AND modified = 1', function (updatedCustomers) {
                asyncLoopFactory(updatedCustomers.length, function (loop) {
                    var data = updatedCustomers.item(loop.iteration());

                    push(data.remote_id, data, function (response) {
                        loop.next();
                    }, function () {
                        loop.next();
                    });

                    // End loop
                }, function () {
                    success(updatedCustomers);
                });
            }, function (getErr) {
                error(getErr);
            });
        }

        /**
         *
         */
        var syncDeletedData = function (success, error) {
            get('remote_id != 0 AND customer = 1 AND modified = 2', function (deletedCustomers) {
                asyncLoopFactory(deletedCustomers.length, function (loop) {
                    var id = deletedCustomers.item(loop.iteration()).remote_id;

                    destroy(id, function (response) {
                        loop.next();
                    }, function (destroyErr) {
                        loop.next();
                    });

                    // end loop
                }, function () {
                    success(deletedCustomers);
                });
            }, function (getErr) {
                error(getErr);
            });
        }

        /**
         *
         */
        var downloadSyncData = function (success, error) {
            pull(null, function (customers) {
  
                customersStorageFactory.removeAll(function () {
                    asyncLoopFactory(customers.length, function (loop) {
                        var data = customers[loop.iteration()];

                        data.remote_id = data.id;
                        delete data.id;

                        customersStorageFactory.save(data, function (customerId) {
                            loop.next();
                        }, function (saveErr) {
                            loop.next();
                        });

                        // End loop
                    }, function () {
                        success(customers);
                    });

                }, function (removeAllErr) {
                    error(removeAllErr);
                });

            }, function (pullErr) {
                error(pullErr);
            });
        }

        /**
         *
         */
        var sync = function (success, error) {
            syncNewData(function () {

                syncUpdatedData(function () {

                    syncDeletedData(function () {

                        downloadSyncData(function (data) {
                            success(data);
                        }, function (downloadErr) {
                            error(downloadErr);
                        });
                    }, function (syncErr) {
                        error(syncErr);
                    });
                }, function (syncErr) {
                    error(syncErr);
                });
            }, function (syncErr) {
                error(syncErr);
            });
        }

        return {
            pull: pull,
            push: push,
            destroy: destroy,
            sync: sync
        }
    });
