(function(context,$) {

    "use strict";

    context.JK = context.JK || {};
    context.JK.BandSetupPhotoScreen = function(app) {
        var self = this;
        var logger = context.JK.logger;
        var rest = context.JK.Rest();
        var bandId;
        var band = {};
        var tmpUploadPath = null;
        var bandDetail = null;
        var bandPhoto;
        var selection = null;
        var targetCropSize = 88;
        var largeCropSize = 200;
        var updatingBandPhoto = false;

        function beforeShow(data) {
            bandId = data.id;
        }

        function afterShow(data) {
            resetForm();
            renderBandPhotoScreen()
        }

        function resetForm() {
            // remove all display errors
            $('#band-setup-photo-content-scroller form .error-text').remove()
            $('#band-setup-photo-content-scroller form .error').removeClass("error")
        }

        function populateBandPhoto(bandDetail) {
            self.bandDetail = bandDetail;
            rest.getBandPhotoFilepickerPolicy({ id:bandId })
                .done(function(filepicker_policy) {
                    var template= context.JK.fillTemplate($('#template-band-setup-photo').html(), {
                        "fp_apikey" : gon.fp_apikey,
                        "data-fp-store-path" : createStorePath(bandDetail) + createOriginalFilename(bandDetail),
                        "fp_policy" : filepicker_policy.policy,
                        "fp_signature" : filepicker_policy.signature
                    });
                    $('#band-setup-photo-content-scroller').html(template);


                    var currentFpfile = determineCurrentFpfile();
                    var currentCropSelection = determineCurrentSelection(bandDetail);
                    renderBandPhoto(currentFpfile, currentCropSelection ? JSON.parse(currentCropSelection) : null);
                })
                .error(app.ajaxError);

        }

        // events for main screen
        function events() {
            // wire up main panel clicks
            $('#band-setup-photo-content-scroller').on('click', '#band-setup-photo-upload', function(evt) { evt.stopPropagation(); handleFilePick(); return false; } );
            $('#band-setup-photo-content-scroller').on('click', '#band-setup-photo-delete', function(evt) { evt.stopPropagation(); handleDeleteBandPhoto(); return false; } );
            $('#band-setup-photo-content-scroller').on('click', '#band-setup-photo-cancel', function(evt) { evt.stopPropagation(); navToEditProfile(); return false; } );
            $('#band-setup-photo-content-scroller').on('click', '#band-setup-photo-submit', function(evt) { evt.stopPropagation(); handleUpdateBandPhoto(); return false; } );
            //$('#band-setup-photo-content-scroller').on('change', 'input[type=filepicker-dragdrop]', function(evt) { evt.stopPropagation(); afterImageUpload(evt.originalEvent.fpfile); return false; } );
        }

        function handleDeleteBandPhoto() {

            if(self.updatingBandPhoto) {
                // protect against concurrent update attempts
                return;
            }

            self.updatingBandPhoto = true;
            renderBandPhotoSpinner();

            rest.deleteBandPhoto({ id: bandId })
                .done(function() {
                    removeBandPhotoSpinner({ delete:true });
                    deleteBandPhotoSuccess(arguments);
                    selection = null;
                })
                .fail(function() {
                    app.ajaxError(arguments);
                    $.cookie('original_fpfile_band_photo', null);
                    self.updatingBandPhoto = false;
                })
                .always(function() {

                })
        }

        function deleteBandPhotoSuccess(response) {

            renderBandPhoto(null, null);

            rest.getBand(bandId)
                .done(function(bandDetail) {
                    self.bandDetail = bandDetail;
                })
                .error(app.ajaxError)
                .always(function() {
                    self.updatingBandPhoto = false;
                })
        }

        function handleFilePick() {
            rest.getBandPhotoFilepickerPolicy({ id: bandId })
                .done(function(filepickerPolicy) {
                    renderBandPhotoSpinner();
                    logger.debug("rendered spinner");
                    filepicker.setKey(gon.fp_apikey);
                    filepicker.pickAndStore({
                            mimetype: 'image/*',
                            maxSize: 10000*1024,
                            policy: filepickerPolicy.policy,
                            signature: filepickerPolicy.signature
                        },
                        { path: createStorePath(self.bandDetail), access: 'public' },
                        function(fpfiles) {
                            removeBandPhotoSpinner();
                            afterImageUpload(fpfiles[0]);
                        }, function(fperror) {
                            removeBandPhotoSpinner();

                            if(fperror.code != 101) { // 101 just means the user closed the dialog
                                alert("unable to upload file: " + JSON.stringify(fperror))
                            }
                        })
                })
                .fail(app.ajaxError);

        }
        function renderBandPhotoScreen() {

            rest.getBand(bandId)
                .done(populateBandPhoto)
                .error(app.ajaxError)
        }

        function navToEditProfile() {
            resetForm();
            context.location = '/client#/band/setup/' + bandId;
        }

        function renderBandPhotoSpinner() {
            var bandPhotoSpace = $('#band-setup-photo-content-scroller .band-setup-photo .avatar-space');
            // if there is already an image tag, we only obscure it.

            var bandPhoto = $('img.preview_profile_avatar', bandPhotoSpace);

            var spinner = $('<div class="spinner spinner-large"></div>')
            if(bandPhoto.length === 0) {
                bandPhotoSpace.prepend(spinner);
            }
            else {
                // in this case, just style the spinner to obscure using opacity, and center it
                var jcropHolder = $('.jcrop-holder', bandPhotoSpace);
                spinner.width(jcropHolder.width());
                spinner.height(jcropHolder.height());
                spinner.addClass('op50');
                var jcrop = bandPhoto.data('Jcrop');
                if(jcrop) {
                    jcrop.disable();
                }
                bandPhotoSpace.append(spinner);
            }
        }

        function removeBandPhotoSpinner(options) {
            var bandPhotoSpace = $('#band-setup-photo-content-scroller .band-setup-photo .avatar-space');

            if(options && options.delete) {
                bandPhotoSpace.children().remove();
            }

            var spinner = $('.spinner-large', bandPhotoSpace);
            spinner.remove();
            var bandPhoto = $('img.preview_profile_avatar', bandPhotoSpace);
            var jcrop = bandPhoto.data('Jcrop')
            if(jcrop) {
                jcrop.enable();
            }
        }

        function renderBandPhoto(fpfile, storedSelection) {

            // clear out
            var bandPhotoSpace = $('#band-setup-photo-content-scroller .band-setup-photo .avatar-space');

            if(!fpfile) {
                renderNoBandPhoto(bandPhotoSpace);
            }
            else {
                rest.getBandPhotoFilepickerPolicy({handle: fpfile.url, id: bandId})
                    .done(function(filepickerPolicy) {
                        bandPhotoSpace.children().remove();
                        renderBandPhotoSpinner();

                        var photo_url = fpfile.url + '?signature=' + filepickerPolicy.signature + '&policy=' + filepickerPolicy.policy;
                        bandPhoto = new Image();
                        $(bandPhoto)
                            .load(function(e) {
                                removeBandPhotoSpinner();

                                bandPhoto = $(this);
                                bandPhotoSpace.append(bandPhoto);
                                var width = bandPhoto.naturalWidth();
                                var height = bandPhoto.naturalHeight();

                                if(storedSelection) {
                                    var left = storedSelection.x;
                                    var right = storedSelection.x2;
                                    var top = storedSelection.y;
                                    var bottom = storedSelection.y2;
                                }
                                else {
                                    if(width < height) {
                                        var left = width * .25;
                                        var right = width * .75;
                                        var top = (height / 2) - (width / 4);
                                        var bottom = (height / 2) + (width / 4);
                                    }
                                    else {
                                        var top = height * .25;
                                        var bottom = height * .75;
                                        var left = (width / 2) - (height / 4);
                                        var right = (width / 2) + (height / 4);
                                    }
                                }

                                // jcrop only works well with px values (not percentages)
                                // so we get container, and work out a decent % ourselves
                                var container = $('#band-setup-photo-content-scroller');

                                bandPhoto.Jcrop({
                                    aspectRatio: 1,
                                    boxWidth: container.width() * .75,
                                    boxHeight: container.height() * .75,
                                    // minSelect: [targetCropSize, targetCropSize], unnecessary with scaling involved
                                    setSelect: [ left, top, right, bottom ],
                                    trueSize: [width, height],
                                    onRelease: onSelectRelease,
                                    onSelect: onSelect,
                                    onChange: onChange
                                });
                            })
                            .error(function() {
                                // default to no avatar look of UI
                                renderNoBandPhoto(bandPhotoSpace);
                            })
                            .attr('src', photo_url)
                            .attr('alt', 'profile avatar')
                            .addClass('preview_profile_avatar');
                    })
                    .fail(app.ajaxError);
            }
        }

        function afterImageUpload(fpfile) {
            $.cookie('original_fpfile_band_photo', JSON.stringify(fpfile));
            renderBandPhoto(fpfile, null);
        }

        function renderNoBandPhoto(bandPhotoSpace) {
            // no photo found for band

            removeBandPhotoSpinner();

            var noAvatarSpace = $('<div></div>');
            noAvatarSpace.addClass('no-avatar-space');
            noAvatarSpace.text('Please upload a photo');
            bandPhotoSpace.append(noAvatarSpace);
        }

        function handleUpdateBandPhoto(event) {

            if(self.updatingBandPhoto) {
                // protect against concurrent update attempts
                return;
            }

            if(selection) {
                var currentSelection = selection;
                self.updatingBandPhoto = true;
                renderBandPhotoSpinner();

                logger.debug("Converting...");

                // we convert two times; first we crop to the selected region,
                // then we scale to 88x88 (targetCropSize X targetCropSize), which is the largest size we use throughout the site.
                var fpfile = determineCurrentFpfile();
                rest.getBandPhotoFilepickerPolicy({ handle: fpfile.url, convert: true, id: bandId })
                    .done(function(filepickerPolicy) {
                        filepicker.setKey(gon.fp_apikey);
                        filepicker.convert(fpfile, {
                                crop: [
                                    Math.round(currentSelection.x),
                                    Math.round(currentSelection.y),
                                    Math.round(currentSelection.w),
                                    Math.round(currentSelection.w)],
                                fit: 'crop',
                                format: 'jpg',
                                quality: 90,
                                policy: filepickerPolicy.policy,
                                signature: filepickerPolicy.signature
                            }, { path: createStorePath(self.bandDetail) + 'cropped-' + new Date().getTime() + '.jpg', access: 'public' },
                            function(cropped) {
                                logger.debug("converting cropped");
                                rest.getBandPhotoFilepickerPolicy({handle: cropped.url, convert: true, id: bandId})
                                    .done(function(filepickerPolicy) {
                                        filepicker.convert(cropped, {
                                                height: targetCropSize,
                                                width: targetCropSize,
                                                fit: 'scale',
                                                format: 'jpg',
                                                quality: 75,
                                                policy: filepickerPolicy.policy,
                                                signature: filepickerPolicy.signature
                                            },  { path: createStorePath(self.bandDetail), access: 'public' },
                                            function(scaled) {

                                                filepicker.convert(cropped, {
                                                        height: largeCropSize,
                                                        width: largeCropSize,
                                                        fit: 'scale',
                                                        format: 'jpg',
                                                        quality: 75,
                                                        policy: filepickerPolicy.policy,
                                                        signature: filepickerPolicy.signature
                                                    },  { path: createStorePath(self.bandDetail) + 'large.jpg', access: 'public' },
                                                    function(scaledLarger) {
                                                        logger.debug("converted and scaled final image %o", scaled);
                                                        rest.updateBandPhoto({
                                                            original_fpfile: determineCurrentFpfile(),
                                                            cropped_fpfile: scaled,
                                                            cropped_large_fpfile: scaledLarger,
                                                            crop_selection: currentSelection,
                                                            id: bandId
                                                        })
                                                        .done(updateBandPhotoSuccess)
                                                        .fail(app.ajaxError)
                                                        .always(function() { removeBandPhotoSpinner(); self.updatingBandPhoto = false;})
                                                    },
                                                    function(fperror) {
                                                        alert("unable to scale larger selection. error code: " + fperror.code);
                                                        removeBandPhotoSpinner();
                                                        self.updatingBandPhoto = false;
                                                    })
                                            },
                                            function(fperror) {
                                                alert("unable to scale selection. error code: " + fperror.code);
                                                removeBandPhotoSpinner();
                                                self.updatingBandPhoto = false;
                                            })
                                    })
                                    .fail(app.ajaxError);
                            },
                            function(fperror) {
                                alert("unable to crop selection. error code: " + fperror.code);
                                removeBandPhotoSpinner();
                                self.updatingBandPhoto = false;
                            }
                        );
                    })
                    .fail(app.ajaxError);
            }
            else {
                app.notify(
                    {   title: "Upload a Band Photo First",
                        text: "To update your band photo, first you must upload an image using the UPLOAD button"
                    },
                    null,
                    true);
            }
        }

        function updateBandPhotoSuccess(response) {
            $.cookie('original_fpfile_band_photo', null);

            self.bandDetail = response;

            app.notify(
                {   title: "Band Photo Changed",
                    text: "You have updated your band photo successfully."
                },
                null,
                true);
        }

        function onSelectRelease(event) {
        }

        function onSelect(event) {
            selection = event;
        }

        function onChange(event) {
        }

        function createStorePath(bandDetail) {
            return gon.fp_upload_dir + '/' + bandDetail.id + '/'
        }

        function createOriginalFilename(bandDetail) {
            // get the s3
            var fpfile = bandDetail.original_fpfile_photo ? JSON.parse(bandDetail.original_fpfile_photo) : null;
            return 'original_band_photo.jpg'
        }

        // retrieves a file that has not yet been used as an band photo (uploaded, but not cropped)
        function getWorkingFpfile() {
            return JSON.parse($.cookie('original_fpfile_band_photo'))
        }

        function determineCurrentFpfile() {
            // precedence is as follows:
            // * tempOriginal: if set, then the user is working on a new upload
            // * storedOriginal: if set, then the user has previously uploaded and cropped a band photo
            // * null: neither are set above

            var tempOriginal = getWorkingFpfile();
            var storedOriginal = self.bandDetail.original_fpfile_photo ? JSON.parse(self.bandDetail.original_fpfile_photo) : null;

            return tempOriginal ? tempOriginal : storedOriginal;
        }

        function determineCurrentSelection(bandDetail) {
            // if the cookie is set, don't use the storage selection, just default to null
            return $.cookie('original_fpfile_band_photo') == null ? bandDetail.crop_selection_photo : null;
        }

        function initialize() {
            var screenBindings = {
                'beforeShow': beforeShow,
                'afterShow': afterShow
            };
            app.bindScreen('band/setup/photo', screenBindings);
            events();
        }

        this.initialize = initialize;
        this.beforeShow = beforeShow;
        this.afterShow = afterShow;
        return this;
    };

})(window,jQuery);