window.pfClientMain = function (contId, params) {
    this.name   = 'pfClient';

    this.error  = null;
    
    this.drawPfSelect = params.select ? params.select : 0;

    this.widget = new pfClientWidgetCore(this);
    this.api    = new pfClientApi(this);
    this.model  = new pfClientModel(this);

    this.contId = contId;
    this.cont   = this.widget.dom(contId);

    this.contMain       = this.widget.create('div', this.cont, 'page');
    this.contError      = this.widget.create('div', this.cont, 'page');
    this.contLoading    = this.widget.create('div', this.cont, 'page');

    this.contPopup      = this.widget.create('div', this.cont, 'popup');
    this.contDebug      = this.widget.create('div', this.cont, 'debug');
    this.contPopup.id   = this.widget.widgetEtc.getPageLinkId();
    this.widget.widgetEtc.pageLink(this.contPopup);

    this.currentUser    = null;     // пользователь, которого мы просматриваем
    this.pfxUrl         = null;
    this.isGuest        = true;     // находимся в режиме гостя
    this.isOwner        = false;    // просматриваем свой альбом
    this.linker         = null;     // объект, который умеет строить ссылки

    this.setDebugOn = function () {
        this.api.debugApi = true;
        this.contDebug.style.display = 'block';
    }

    this.hidePages = function () {
        this.contMain.style.display     = 'none';
        this.contError.style.display    = 'none';
        this.contLoading.style.display  = 'none';
    }

    this.showPage = function (cont) {
        cont.style.display = 'block';
    }

    this.pageLoading = function () {
        this.hidePages();
        this.widget.clear(this.contLoading);
        this.widget.widgetEtc.pageLoading(this.contLoading);
        this.showPage(this.contLoading);
    }

    this.pageMainAgain = function () {
        this.hidePages();
        this.showPage(this.contMain);
    }

    this.pageError = function (msg, code) {
        this.error = msg;
        this.hidePages();
        this.widget.clear(this.contError);
        this.widget.widgetEtc.pageError(this.contError, msg, code);
        this.showPage(this.contError);
    }

    this.pageAlbums = function (page) {
        var albums = this.model.getAllAlbums();

        if (albums == undefined || albums == null || albums.length == 0) {
            this.pageUpload();
        }
        else {
            this.hidePages();
            if (page == undefined || page == null) {
                page = 1;
            }

            this.widget.clear(this.contMain);
            this.widget.widgetAlbums.pageAlbums(this.contMain, albums, page);
            this.showPage(this.contMain);
        }
    }

    this.pageEditAlbum = function (albumId) {
        var main    = this;
        var album   = main.model.getAlbum(albumId);

        this.hidePages();
        this.widget.clear(this.contMain);
        this.widget.widgetAlbums.pageEditAlbum(this.contMain, album);
        this.showPage(this.contMain);
    }


    this.pageSmallPhotos = function (albumId, page) {
        this.hidePages();
        if (page == undefined || page == null) {
            page = 1;
        }

        this.widget.clear(this.contMain);
        this.widget.widgetPhotos.pageSmallPhotos(this.contMain, this.model.getAlbum(albumId), page);
        this.showPage(this.contMain);
    }

    this.pageSmallPhotosView = function (albumId, page) {
        this.hidePages();
        if (page == undefined || page == null) {
            page = 1;
        }
        this.widget.clear(this.contMain);
        this.widget.widgetPhotos.pageSmallPhotosView(this.contMain, this.model.getAlbum(albumId), page);
        this.showPage(this.contMain);
    }    
    
    this.pageNoPhotos = function (albumId) {
        this.hidePages();
        this.widget.clear(this.contMain);
        this.widget.widgetEtc.pageNoPhotos(this.contMain, this.model.getAlbum(albumId));
        this.showPage(this.contMain);
    }

    this.pageLargePhotos = function (albumId, photoIdx) {
        this.hidePages();

        if (photoIdx == undefined || photoIdx == null ) {
            photoIdx = 0;
        }

        this.widget.clear(this.contMain);
        this.widget.widgetPhotos.pageLargePhotos(this.contMain, this.model.getAlbum(albumId), photoIdx);

        this.showPage(this.contMain);
    }

    this.pageUpload = function (albumId) {
        var main = this;
        this.hidePages();

        var album = null;

        if (albumId != undefined || albumId != null ) {
            album   = main.model.getAlbum(albumId);
        }

        this.widget.clear(this.contMain);
        this.widget.widgetUpload.pageUpload(this.contMain, album);

        this.showPage(this.contMain);
    }
    
    this.run = function (pfxUrl) {

        var ex = null;

        try {
            var login   = getCookie('login');
            var domain  = getCookie('domain');
            var id      = getCookie('id');

            if (login && domain && id) {
                this.boot(login, domain, id, pfxUrl);
            }
            else {
                throw 'Необходимо быть авторизованным пользователем, что бы просматривать альбом';
            }
        }
        catch (ex) {
            this.pageError(ex);
        }
    }

    this.linkConstructor = function (pfxUrl, login) {
        this.pfxUrl = pfxUrl;
        this.login  = login;

        this.linkAlbums = function (page) {
            return this.pfxUrl+this.getLoginSfx()+this.getPageSfx(page);
        }

        this.linkSmallPhotos = function (albumId, page) {
            return this.pfxUrl+this.getLoginSfx()+'small/'+parseInt(albumId)+'/'+this.getPageSfx(page);
        }

        this.linkLargePhotos = function (albumId, photoId) {
            return this.pfxUrl+this.getLoginSfx()+'large/'+parseInt(albumId)+'/'+parseInt(photoId)+'/';
        }

        this.getLoginSfx = function () {
            return escape(this.login.replace('@', '.')) + '/'
        }

        this.getPageSfx = function (page) {
            if (page == undefined || page == null || typeof(page) != 'number') {
                return '';
            }

            var p = parseInt(page);
            return p > 1 ? '' + p + '/' : '';
        }
    }

    this.bootFake = function (pfxUrl) {
        //this.setDebugOn();

        this.pfxUrl     = pfxUrl;
        this.wrapper    = new this.wrapperFake();
        this.linker     = new this.linkConstructor(this.pfxUrl, this.currentUser);
        this.wrapper.pageAlbums();
    }

    this.boot = function (login, domain, id, pfxUrl) {
        //this.setDebugOn();

        this.pfxUrl     = pfxUrl;

        var result      = [];
        var currentLoc  = new pfLocationParser();
        var pfxLoc      = new pfLocationParser(pfxUrl);

        if (result = currentLoc.pathStr.match('^'+pfxLoc.pathStr+'([^/]+)/((\\d+)/)?$')) {
            this.installWrapper(login, domain, id, result[1]);
            this.wrapper.pageAlbums(result[3] == undefined || result[3] == "" ? 1 : parseInt(result[3]));
        }
        else if (result = currentLoc.pathStr.match('^'+pfxLoc.pathStr+'([^/]+)/small/(\\d+)/((\\d+)/)?$')) {
            this.installWrapper(login, domain, id, result[1]);
            this.wrapper.pagePhotosSmall(
                parseInt(result[2])
              , result[4] == undefined || result[4] == "" ? 1 : parseInt(result[4])
            );
        }
        else if (result = currentLoc.pathStr.match('^'+pfxLoc.pathStr+'([^/]+)/large/(\\d+)/(\\d+)/$')) {
            this.installWrapper(login, domain, id, result[1]);
            this.wrapper.pagePhotosLarge(
                parseInt(result[2])
              , parseInt(result[3])
            );
        }
        else {
            throw 'Неправильно построенная ссылка '+currentLoc.pathStr+"\nПрефикс: "+pfxLoc.pathStr;
        }
    }

    this.installWrapper = function (login, domain, id, currentUser) {
        var result;
        if (result = currentUser.match('^(.+)\\.([^\\.]+\\.[^\\.]+)')) {
            currentUser = result[1]+'@'+result[2];
        }
        else {
            throw 'Неправильно построенная ссылка - логин в невалидном формате: '+currentUser;
        }

        this.authLogin      = login;
        this.authDomain     = domain
        this.authId         = id;
        this.authUser       = login + '@' + domain;
        this.currentUser    = currentUser;
        this.linker         = new this.linkConstructor(this.pfxUrl, this.currentUser);

        if (this.currentUser == this.authUser) {
            this.wrapper = new this.wrapperPochtaUser(login, domain, id);
        }
        else {
            this.wrapper = new this.wrapperPochtaGuest(currentUser);
        }

    }

    this.wrapperBase = function (main) {
        this.main = main;

        this.pagePhotos = function (albumId, page) {
            this.pagePhotosSmall(albumId, page);
        }

        /* page large photos */

        this.pagePhotosLarge = function (albumId, photoId) {
            var self        = this;
            var toAlbumId   = albumId;

            this.pagePhotosCommon(
                function () {
                    self.pagePhotosLargeReal(albumId, photoId);
                }
              , albumId
            );
        }

        
        this.pagePhotosLargeReal = function (albumId, photoId) {

            var album = this.main.model.getAlbum(albumId);

            if (album.photos.length == 0) {
                this.pageNoPhotos(album.id);
            }
            else {
                var photoIdx    = -1;
                var photos      = album.photos;
                var idx         = 0;
                var idxMax      = photos.length;

                if (photoId == null || photoId == null) {
                    photoIdx = 0;
                }
                else {
                    for (idx = 0; idx < idxMax; idx++) {
                        if (photos[idx].id == photoId) {
                            photoIdx = idx;
                            break;
                        }
                    }
                }

                if (photoIdx == -1) {
                    this.pageNoSuchPhoto(album.id, photoId);
                }
                else {
                    this.main.pageLargePhotos(album.id, photoIdx);
                }
            }
        }


        /* page small photos */

        this.pagePhotosSmall = function (albumId, page) {
            var self        = this;

            this.pagePhotosCommon(
                function () {
                    self.pagePhotosSmallReal(albumId, page);
                }
              , albumId
            );
        }


        this.pagePhotosSmallReal = function (albumId, page) {

            var album = this.main.model.getAlbum(albumId);

            if (album.photos.length == 0) {
                this.pageNoPhotos(album.id);
            }
            else {
                this.main.pageSmallPhotos(album.id, page);
            }
        }

        /* all photos */

        this.pagePhotosCommon = function (realCb, albumId, p2) {
            var main    = this.main;

            if (this.isAuthorized) {
                main.wrapper.pagePhotosCommonPre(realCb, albumId, p2);
            }
            else {
                this.authorize(
                    function () {
                        main.wrapper.pagePhotosCommonPre(realCb, albumId, p2)
                    }
                );
            }
        }

        this.pagePhotosCommonPre = function (realCb, albumId, p2) {
            var main    = this.main;
            var ex      = null;
            var album   = null;

            try {
                album = main.model.getAlbum(albumId);
            }
            catch (ex) {
                this.pageNoSuchAlbum(albumId);
            }

            if (album.photos == undefined || album.photos == null || typeof(album.photos) != "object") {
                this.loadPhotos(realCb, albumId, p2);
            }
            else {
                realCb(album, p2);
            }
        }

        /* page albums */

        this.pageAlbums = function (page) {
            var main    = this.main;

            if (this.isAuthorized) {
                main.pageAlbumsReal(page);
            }
            else {
                this.authorize(
                    function () {
                        main.wrapper.pageAlbumsReal(page);
                    }
                );
            }
        }
        
        this.pageAlbumsReal = function (page) {

            var main    = this.main;
            var albums  = main.model.getAllAlbums();

            if (albums == undefined || albums == null || albums.length == 0) {
                this.pageNoAlbums();
            }
            else {
                main.hidePages();
                if (page == undefined || page == null) {
                    page = 1;
                }

                main.widget.clear(main.contMain);
                main.widget.widgetAlbums.pageAlbums(main.contMain, albums, page);
                main.showPage(main.contMain);
            }
        }

        /* utils */

        this.pageNoPhotos = function (albumId) {
            throw "У пользователя "+this.user+" в альбоме "+albumId+" нет доступных фото";
        }

        this.pageNoSuchAlbum = function (albumId) {
            throw "У пользователя "+this.user+" нет альбома "+albumId;
        }

        this.pageNoSuchPhoto = function (albumId, photoId) {
            throw "У пользователя "+this.user+" в альбоме "+albumId+" нет фото "+photoId;
        }

        this.pageNoAlbums = function () {
            throw "У пользователя "+this.user+" нет достпных альбомов";
        }

        this.authorize = function (cb, p1, p2, p3) {
            throw 'methos authorize must be implemented in real wrapper';
        }

        this.loadPhotos = function (realCb, albumId, p2) {
            throw 'methos loadPhotos must be implemented in real wrapper';
        }
    }


    this.wrapperPochtaUser = function (login, domain, id) {

        this.login              = login;                // логин авторизованного пользователя почты
        this.domain             = domain;               // домен авторизованного пользователя почты
        this.user               = login + '@' + domain; // авторизованный пользователь почты
        this.id                 = id;                   // сессия авторизованного пользователя на почте
        this.isAuthorized       = false;

        this.main.isGuest       = false;
        this.main.isOwner       = true;
        this.main.currentUser   = this.user;

        this.authorize = function (cb, p1, p2, p3) {
            var main = this.main;
            main.api.callAuthParntersUser(this.user, this.id, function (answer) {
                main.api.sid = answer.sid;
                main.model.setAllAlbums(answer.albums);
                main.model.setAllGenres(answer.genres);
                main.wrapper.isAuthorized = true;
                cb(p1, p2, p2);
            });
        }

        this.loadPhotos = function (realCb, albumId, p2) {
            var main = this.main;

            main.api.callPhotos(albumId, function (answer) {
                main.model.setPhotos(answer.albumId, answer.photos);
                main.wrapper.pagePhotosCommonPre(realCb, albumId, p2);
            });
        }

        this.pageNoAlbums = function () {
            this.main.pageUpload();
        }

        this.pageNoPhotos = function (albumId) {
            this.main.pageSmallPhotos(albumId);
        }
    }

    this.wrapperPochtaUser.prototype = new this.wrapperBase(this);

    this.wrapperPochtaGuest = function (currentUser) {

        this.user               = currentUser;
        this.isAuthorized       = false;

        this.main.isGuest       = true;
        this.main.isOwner       = false;
        this.main.currentUser   = this.user;

        this.authorize = function (cb, p1, p2, p3) {
            var main = this.main;
            main.api.callGuestAlbumList(this.user, function (answer) {
                main.api.sid = null;
                main.model.setAllAlbums(answer.albums);
                main.model.setAllGenres(answer.genres);
                main.wrapper.isAuthorized = true;
                cb(p1, p2, p2);
            });
        }

        this.loadPhotos = function (realCb, albumId, p2) {
            var main = this.main;

            main.api.callGuestAlbumContent(this.user, albumId, function (answer) {
                main.model.setPhotos(answer.albumId, answer.photos);
                main.wrapper.pagePhotosCommonPre(realCb, albumId, p2);
            });
        }
    }


    this.wrapperPochtaGuest.prototype = new this.wrapperBase(this);

    this.wrapperFake = function () {

        this.isAuthorized       = false;

        this.main.isGuest       = false;
        this.main.isOwner       = true;
        this.main.currentUser   = 'fake@site.com';

        this.authorize = function (cb, p1, p2, p3) {
            var main        = this.main;
            main.api.sid    = 'fake-sid';
            main.model.loadExamples();
            main.wrapper.isAuthorized = true;
            cb(p1, p2, p2);
        }

        this.loadPhotos = function (realCb, albumId, p2) {
            var main = this.main;
            main.model.setPhotos(albumId, []);
            main.wrapper.pagePhotosCommonPre(realCb, albumId, p2);
        }

        this.pageNoPhotos = function (albumId) {
            this.main.pageNoPhotos(albumId);
        }
    }

    this.wrapperFake.prototype = new this.wrapperBase(this);

    // Tab control, depends on prototype
    this.artistsTabOnClick = function (tab) {
        if (this.canSelectTab(tab)) {
            this.selectTab(tab);
            this.wrapper.pagePhotos(this.model.getArtistsAlbumId());
        }
    }

    this.coversTabOnClick = function (tab) {
        if (this.canSelectTab(tab)) {
            this.selectTab(tab);
            this.wrapper.pagePhotos(this.model.getCoversAlbumId());
        }
    }

    this.canSelectTab = function (tab) {
        if(Element.hasClassName(tab, 'ActiveTab') || this.contLoading.style.display == 'block') {
            return false;
        }
        else {
            return true;
        }
    }

    this.selectTab = function (el){
        var tabs = $A(el.siblings());

        tabs.each(function(node){
            Element.removeClassName(node,'ActiveTab');
        });

        Element.addClassName(el,'ActiveTab');
    }
    
    // DEPRICATED
    this.photofileRunDepricated = function (login, password) {
        var main = this;

        main.api.callAuth(login, password, function (answer) {
            main.api.sid = answer.sid;
            main.model.setAllAlbums(answer.albums);
            main.model.setAllGenres(answer.genres);

            main.pageAlbums();
        });
    }


    // DEPRICATED
    this.pagePhotosDepricated = function (albumId) {
        var main    = this;
        var album   = main.model.getAlbum(albumId);

        if (album.photos != null && typeof(album.photos) == "object") {
            if (album.photos.length) {
                main.pageSmallPhotos(albumId);
            }
            else {
                this.pageUpload(albumId);
            }
        }
        else {
            main.api.callPhotos(albumId, function (answer) {
                main.model.setPhotos(answer.albumId, answer.photos);
                main.pageSmallPhotos(albumId);
            });
        }
    }

    /* Photofile emulator */

    this.runPhotofile = function (pfxUrl, login, password) {

        var ex = null;

        try {
            this.bootPhotofile(login, password, pfxUrl);
        }
        catch (ex) {
            this.pageError(ex);
        }
    }

    this.bootPhotofile = function (login, password, pfxUrl) {
        //this.setDebugOn();

        this.pfxUrl     = pfxUrl;

        var result      = [];
        var currentLoc  = new pfLocationParser();
        var pfxLoc      = new pfLocationParser(pfxUrl);

        this.installWrapperPhotofile (login, password, login /*looking at current user*/);
        this.wrapper.firstPage();
    }

    this.installWrapperPhotofile = function (login, password, currentUser) {
        this.authLogin      = login;
        this.authDomain     = 'site.com';
        this.authUser       = login;
        this.currentUser    = currentUser;
        this.linker         = new this.linkConstructor(this.pfxUrl, this.currentUser);

        if (this.currentUser == this.authUser) {
            this.wrapper = new this.wrapperPhotofileUser(login, password);
        }
        else {
            //this.wrapper = new this.wrapperPochtaGuest(currentUser);
            throw "wrapperPhotofileGuest is under construction";
        }

    }

    this.wrapperPhotofileUser = function (login, password) {

        this.login              = login;                // логин юзера на фотофайле
        this.password           = password;             // пароль юзера на фотофайле
        this.user               = login;
        this.isAuthorized       = false;

        this.main.isGuest       = false;
        this.main.isOwner       = true;
        this.main.currentUser   = this.user;

        this.authorize = function (cb, p1, p2, p3) {
            var main = this.main;
            main.api.callAuth(this.login, this.password, function (answer) {
                main.api.sid = answer.sid;
                main.model.setAllAlbums(answer.albums);
                main.model.setAllGenres(answer.genres);
                main.wrapper.isAuthorized = true;
                cb(p1, p2, p2);
            });
        }

        this.loadPhotos = function (realCb, albumId, p2) {
            var main = this.main;

            main.api.callPhotos(albumId, function (answer) {
                main.model.setPhotos(answer.albumId, answer.photos);
                main.wrapper.pagePhotosCommonPre(realCb, albumId, p2);
            });
        }

        this.pageNoAlbums = function () {
            this.main.pageUpload();
        }

        this.pageNoPhotos = function (albumId) {
            this.main.pageNoPhotos(albumId);
        }

        this.firstPage = function () {

            var main    = this.main;

            if (this.isAuthorized) {
                main.wrapper.pagePhotos(main.model.getArtistsAlbumId());
            }
            else {
                this.authorize(
                    function () {
                        main.wrapper.pagePhotos(main.model.getArtistsAlbumId());
                    }
                );
            }
        }
    }

    this.wrapperPhotofileUser.prototype = new this.wrapperBase(this);

    /* Delit */

    this.runDelit = function (pfxUrl, lookingLogin, authLogin, authSid, albumKind) {
        try {
            this.bootDelit(pfxUrl, lookingLogin, authLogin, authSid, albumKind);
        }
        catch (ex) {
            this.pageError(ex);
        }
    }
    this.bootDelit = function (pfxUrl, lookingLogin, authLogin, authSid, albumKind) {
        //this.setDebugOn();

        this.pfxUrl     = pfxUrl;

        var result      = [];
        var currentLoc  = new pfLocationParser();
        var pfxLoc      = new pfLocationParser(pfxUrl);

        this.installWrapperDelit (authLogin, authSid, lookingLogin);
        this.wrapper.firstPage(albumKind);
    }

    this.installWrapperDelit = function (login, sid, currentUser) {
        this.authLogin      = login;
        this.authDomain     = 'site.com';
        this.authUser       = login;
        this.currentUser    = currentUser;
        this.linker         = new this.linkConstructor(this.pfxUrl, this.currentUser);

        if (this.currentUser == this.authUser) {
            this.wrapper = new this.wrapperDelitUser(login, sid);
        }
        else {
            this.wrapper = new this.wrapperDelitGuest(currentUser);
        }
    }

    this.wrapperDelitGuest = function (currentUser) {

        this.user               = currentUser + '@' + 'delit.net';
        this.isAuthorized       = false;

        this.main.isGuest       = true;
        this.main.isOwner       = false;
        this.main.currentUser   = this.user;

        this.authorize = function (cb, p1, p2, p3) {
            var main = this.main;
            main.api.callGuestAlbumList(this.user, function (answer) {
                main.api.sid = null;
                main.model.setAllAlbums(answer.albums);
                main.model.setAllGenres(answer.genres);
                main.wrapper.isAuthorized = true;
                cb(p1, p2, p2);
            });
        }

        this.loadPhotos = function (realCb, albumId, p2) {
            var main = this.main;

            main.api.callGuestAlbumContent(this.user, albumId, function (answer) {
                main.model.setPhotos(answer.albumId, answer.photos);
                main.wrapper.pagePhotosCommonPre(realCb, albumId, p2);
            });
        }

        this.pageNoPhotos = function (albumId) {
            this.main.pageNoPhotos(albumId);
        }

        this.firstPage = function () {

            var main    = this.main;

            if (this.isAuthorized) {
                main.wrapper.pagePhotos(main.model.getArtistsAlbumId());
            }
            else {
                this.authorize(
                    function () {
                        main.wrapper.pagePhotos(main.model.getArtistsAlbumId());
                    }
                );
            }
        }

    }

    this.wrapperDelitGuest.prototype = new this.wrapperBase(this);

    this.wrapperDelitUser = function (login, id) {

        this.login              = login;                // логин авторизованного пользователя delit.net
        this.domain             = 'delit.net';          // не используется
        this.user               = login;                // юзер делита
        this.id                 = id;                   // сессия авторизованного пользователя на почте
        this.isAuthorized       = false;

        this.main.isGuest       = false;
        this.main.isOwner       = true;
        this.main.currentUser   = this.user;

        this.authorize = function (cb, p1, p2, p3) {
            var main = this.main;
            main.api.callAuthParntersUser(this.user, this.id, function (answer) {
                main.api.sid = answer.sid;
                main.model.setAllAlbums(answer.albums);
                main.model.setAllGenres(answer.genres);
                main.wrapper.isAuthorized = true;
                cb(p1, p2, p2);
            });
        }

        this.loadPhotos = function (realCb, albumId, p2) {
            var main = this.main;

            main.api.callPhotos(albumId, function (answer) {
                main.model.setPhotos(answer.albumId, answer.photos);
                main.wrapper.pagePhotosCommonPre(realCb, albumId, p2);
            });
        }

        this.pageNoPhotos = function (albumId) {
            this.main.pageNoPhotos(albumId);
        }

        this.firstPage = function (albumKind) {

            var main    = this.main;

            if (this.isAuthorized) {
                if (albumKind == 'covers')
                    main.wrapper.pagePhotos(main.model.getCoversAlbumId());
                else
                    main.wrapper.pagePhotos(main.model.getArtistsAlbumId());
            }
            else {
                this.authorize(
                    function () {
                        if (albumKind == 'covers')
                            main.wrapper.pagePhotos(main.model.getCoversAlbumId());
                        else
                            main.wrapper.pagePhotos(main.model.getArtistsAlbumId());
                    }
                );
            }
        }
    }

    this.wrapperDelitUser.prototype = new this.wrapperBase(this);
}

