window.pfClientApiException = function (message,code) {
    this.message    = message;
    this.code       = code;
}

window.pfClientApiPhotofileException = function (message,code) {
    this.message    = message;
    this.code       = code;
}

window.pfClientApi = function (main) {
    this.main   = main;

    this.debugApi = false;

    this.url    = '/gw.php';

    this.sid    = null;

    this.getLoadingPageUrl = function () {
        return this.url + '/loading.html';
    }

    this.callAuth = function (login, password, cb) {
        var query = {
            'method': 'auth'
          , 'params': {
                'login'     : '' + login
              , 'password'  : '' + password
            }
        }

        this.call(query, cb);
    }

    this.callAuthParntersUser = function (externalLogin, externalSid, cb) {
        var query = {
            'method': 'authPartnersUser'
          , 'params': {
                'externalLogin': '' + externalLogin
              , 'externalSid'  : '' + externalSid
            }
        }

        this.call(query, cb);
    }

    this.callAlbumCreate = function (title, desc, genreId, password , cb) {
        var query = {
            'method': 'albumCreate'
          , 'params': {
                'sid'       : '' + this.sid
              , 'title'     : '' + title
              , 'desc'      : '' + desc
              , 'genreId'   : parseInt(genreId)
              , 'password'  : '' + password
              , 'pwdChanged': true
            }
        }

        this.call(query, cb);
    }

    this.callAlbumCreateFast = function (fakeAlbumId , cb) {
        var query = {
            'method': 'albumCreateFast'
          , 'params': {
                'sid'           : '' + this.sid
              , 'fakeAlbumId'   : '' + fakeAlbumId
            }
        }

        this.call(query, cb);
    }


    this.callAlbumUpdate = function (albumId, title, desc, genreId, password , cb) {
        var query = {
            'method': 'albumUpdate'
          , 'params': {
                'sid'       : '' + this.sid
              , 'albumId'   : parseInt(albumId)
              , 'title'     : '' + title
              , 'desc'      : '' + desc
              , 'genreId'   : parseInt(genreId)
              , 'password'  : password == undefined || password == null ? '' : '' + password
              , 'pwdChanged': password == undefined || password == null ? false : true
            }
        }

        this.call(query, cb);
    }

    this.callAlbumDelete = function (albumId, cb) {
        var query = {
            'method': 'albumDelete'
          , 'params': {
                'sid'       : '' + this.sid
              , 'albumId'   : parseInt(albumId)
            }
        }

        this.call(query, cb);
    }

    this.callPhotos = function (albumId, cb) {
        var query = {
            'method': 'photos'
          , 'params': {
                'sid'       : '' + this.sid
              , 'albumId'   : parseInt(albumId)
            }
        }

        this.call(query, cb);
    }

    this.callUploadGetUrl = function (albumId, title, cb) {
        var query = {
            'method': 'uploadGetUrl'
          , 'params': {
                'sid'       : '' + this.sid
              , 'albumId'   : parseInt(albumId)
              , 'title'     : '' + title
            }
        }

        this.call(query, cb);
    }

    this.callPhotoDelete = function (albumId, photos, cb) {
        this.callQuery('photoDelete', {

            'albumId'   : albumId
          , 'photos'    : photos

        }, cb);
    }

    this.callPhotoMove = function (fromId, toId, photos, cb) {
        this.callQuery('photoMove', {

            'fromId'    : fromId
          , 'toId'      : toId
          , 'photos'    : photos

        }, cb);
    }

    this.callPhotoUpdate = function (albumId, photos, cb) {
        this.callQuery('photoUpdate', {

            'albumId'   : albumId
          , 'photos'    : photos

        }, cb);
    }

    this.callPhotoRotateClockwise = function (photoId, cb) {
        this.callQuery('photoRotate', {

            'photoId'   : photoId
          , 'angle'     : 'RIGHT'

        }, cb);
    }

    this.callPhotoRotateAntiClockwise = function (photoId, cb) {
        this.callQuery('photoRotate', {

            'photoId'   : photoId
          , 'angle'     : 'LEFT'

        }, cb);
    }

    this.callGuestAlbumList = function (login, cb) {
        this.callQuery('guestAlbumList', {

            'login' : login

        }, cb);
    }

    this.callGuestAlbumContent = function (login, albumId, cb) {
        this.callQuery('guestAlbumContent', {

            'login' : login
          , 'id'    : albumId

        }, cb);
    }

    this.callPhotoChangeTitle = function (albumId, photoId, title, cb) {
        var photo = this.main.model.getPhotoById(albumId, photoId);
        this.callPhotoUpdate(albumId, {'id':photoId, 'title':title, 'pos':photo.pos}, cb);
    }

    this.callPhotoChangePosition = function (albumId, photoIdx, move, cb) {
        var album = this.main.model.getAlbum(albumId);

        if (album.photos == undefined || album.photos == null) {
            throw "Операция по  перемещению фотки должна вызываться для альбома с загруженными фотками";
        }

        if (album.photos[photoIdx] == undefined || album.photos[photoIdx] == null) {
            throw "В альбоме "+albumId+" нет фотографии с индексом "+photoIdx;
        }

        if (move == 0) {
            throw "Операция по  перемещению фотки должна вызываться с ненулевым move";
        }

        var j;
        var photos = [];

        // сдвиг влево
        if (move < 0) {
            var from = photoIdx + move < 0 ? 0 : photoIdx + move;
            var to   = photoIdx;

            if (to - from <= 0) {
                return;
            }

            for (j = from; j < to; j++) {
                photos[photos.length] = {'id':album.photos[j].id, 'title':album.photos[j].title, 'pos':album.photos[j+1].pos};
            }

            photos[photos.length] = {'id':album.photos[to].id, 'title':album.photos[to].title, 'pos':album.photos[from].pos}
        }
        // сдвиг вправо
        else {
            var from = photoIdx;
            var to   = photoIdx + move < album.photos.length ? photoIdx + move : album.photos.length - 1;

            if (to - from <= 0) {
                return;
            }

            photos[photos.length] = {'id':album.photos[from].id, 'title':album.photos[from].title, 'pos':album.photos[to].pos}

            for (j = from + 1; j <= to; j++) {
                photos[photos.length] = {'id':album.photos[j].id, 'title':album.photos[j].title, 'pos':album.photos[j-1].pos};
            }

            this.main.debug = photos;
        }

        this.callPhotoUpdate(albumId, photos, cb);
    }

    this.callQuery = function (method, params, cb) {
        if (this.sid && params != undefined && params != null && typeof(params) == 'object') {
            params.sid = this.sid;
        }

        var query = {
            'method': method
          , 'params': params
        }

        this.call(query, cb);
    }

    this.call = function (query, cb) {
        this.main.pageLoading();

        var main    = this.main;
        var self    = this;
        var url     = this.url;

        new Ajax.Request(
            this.url,
            {
                'method'        :'post'
              , 'parameters'    : this.debugApi ?
                    {'query': Object.toJSON(query), 'debug_api': 1}
                  : {'query': Object.toJSON(query)}

              , 'onSuccess'     : function (transport) {
                    var response = transport.responseText;

                    if (!response) {
                        throw "От сервера API не пришёл ответ";
                    }

                    if (typeof(response) != "string") {
                        throw "От сервера API пришёл некорректный ответ в формате "+typeof(response);
                    }

                    var res = "";

                    try {
                        res = response.evalJSON();
                    }
                    catch (ex) {
                        throw "Нет мочи разобрать ответ сервера API\n"+ex;
                    }

                    if (res == undefined || res == null || typeof(res) != "object") {
                        throw "От сервера API пришёл ответ в неизвестном формате "+typeof(res);
                    }

                    if (self.debugApi) {
                        main.widget.widgetEtc.debugPFApi(res);
                    }

                    if (res.exception != undefined) {
                        if (res.exception.is_pf) {
                            throw new pfClientApiPhotofileException (res.exception.message, res.exception.code);
                        }
                        else {
                            throw new pfClientApiException (res.exception.message, res.exception.code);
                        }
                    }

                    if (res.answer == undefined) {
                        throw "Нет мочи найти в ответе сервера API данные";
                    }

                    cb(res.answer);
                }

              , 'on404'         : function (request, transport, json) {
                    main.pageError('Нет соединения с сервером API по адресу '+url, 404);
                }

              , 'onFailure'     : function (request, transport, json) {
                    main.pageError('Возникла ошибка коммуникации с сервером API по адресу '+url);
                }

              , 'onException'   : function (request, exception) {
                    main.pageError(exception);
                }
            }
        );
    }
}

