'use strict';

pandora.ui.mediaView = function(options) {

    var canRemove = pandora.hasCapability('canRemoveItems') || options.editable,
        self = {},
        keys = ['title', 'director', 'year', 'id'],
        listKeys = keys.filter(function(key) {
            var itemKey = Ox.getObjectById(pandora.site.itemKeys, key)
            return itemKey ? Ox.isArray(itemKey.type) : false;
        }),
        that = Ox.Element({}, self)
            .defaults({
                id: ''
            })
            .options({});

    self.filesQuery = {
        conditions: [{
            key: 'id',
            value: options.id,
            operator: '=='
        }]
    };
    self.numberOfItems = 0;
    self.selected = [];
    self.wasChecked = false;

    self.$toolbar = Ox.Bar({
        size: 24
    });

    self.$menu = Ox.MenuButton({
            items: [
                {
                    disabled: true,
                    id: 'ignore',
                    title: Ox._('Ignore Selected Files')
                },
                {},
                {
                    disabled: !canRemove,
                    id: 'delete',
                    title: Ox._('Delete {0}...', [Ox._(pandora.site.itemName.singular)])
                }
            ],
            title: 'set',
            type: 'image'
        })
        .css({
            float: 'left',
            margin: '4px'
        })
        .bindEvent({
            click: function(data) {
                if (data.id == 'ignore') {
                    ignoreFiles();
                } else if (data.id == 'delete') {
                    deleteItem();
                }
            }
        })
        .appendTo(self.$toolbar);

    self.$saveButton = Ox.Button({
            disabled: true,
            title: Ox._('Save Changes'),
            width: 128
        })
        .css({
            float: 'right',
            margin: '4px'
        })
        .bindEvent({
            click: saveChanges
        })
        .appendTo(self.$toolbar);

    self.$filesList = Ox.TableList({
            columns: [
                {
                    clickable: function(data) {
                        return ['uploading', 'queued', 'encoding'].indexOf(data.state) == -1;
                    },
                    format: function(value, data) {
                        var opacity = value
                            || ['encoding', 'failed', 'queued', 'uploading', 'wanted'].indexOf(data.state) > -1
                            ? 1 : 0;
                        return $('<img>')
                            .attr({
                                src: Ox.UI.getImageURL('symbol' + ({
                                    'available': 'Check',
                                    'encoding': 'Sync',
                                    'failed': 'Warning',
                                    'queued': 'Data',
                                    'uploading': 'Upload',
                                    'wanted': 'Up',
                                }[data.state] || 'Check'))
                            })
                            .css({
                                width: '10px',
                                height: '10px',
                                padding: '3px',
                                opacity: opacity
                            });
                    },
                    id: 'selected',
                    operator: '-',
                    title: Ox._('Status'),
                    titleImage: 'check',
                    tooltip: function (data) {
                        return ['uploading', 'queued', 'encoding', 'failed'].indexOf(data.state) > -1
                            ? Ox._({
                                'uploading': 'Video is currently uploaded to server',
                                'queued': 'Waiting for server to process video',
                                'encoding': 'Processing video on server',
                                'failed': 'Encoding failed'
                            }[data.state])
                            : (
                                data.instances.filter(function(i) {return i.ignore; }).length > 0 ||
                                (data.instances.length == 0 && !data.selected)
                            )
                            ? Ox._('Use this file')
                            : Ox._('Dont use this file');
                    },
                    visible: true,
                    width: 16
                },
                {
                    align: 'left',
                    id: 'users',
                    operator: '+',
                    title: Ox._('Users'),
                    visible: true,
                    width: 60
                },
                {
                    align: 'left',
                    id: 'path',
                    operator: '+',
                    title: Ox._('Path'),
                    visible: true,
                    width: 360
                },
                {
                    align: 'left',
                    id: 'folder',
                    operator: '+',
                    title: Ox._('Folder'),
                    visible: false,
                    width: 360
                },
                {
                    align: 'left',
                    id: 'filename',
                    operator: '+',
                    title: Ox._('Filename'),
                    visible: false,
                    width: 360
                },
                {
                    editable: true,
                    id: 'version',
                    operator: '+',
                    title: Ox._('Version'),
                    visible: true,
                    width: 120
                },
                {
                    editable: true,
                    id: 'part',
                    operator: '+',
                    title: Ox._('Part'),
                    visible: true,
                    width: 60
                },
                {
                    editable: true,
                    id: 'partTitle',
                    operator: '+',
                    title: Ox._('Part Title'),
                    visible: true,
                    width: 120
                },
                {
                    editable: true,
                    id: 'language',
                    operator: '+',
                    title: Ox._('Language'),
                    visible: true,
                    width: 60
                },
                {
                    editable: true,
                    id: 'extension',
                    operator: '+',
                    title: Ox._('Extension'),
                    visible: true,
                    width: 60
                },
                {
                    align: 'left',
                    id: 'type',
                    operator: '+',
                    title: Ox._('Type'),
                    visible: true,
                    width: 60
                },
                {
                    align: 'right',
                    format: {type: 'value', args: ['B']},
                    id: 'size',
                    operator: '-',
                    title: Ox._('Size'),
                    visible: true,
                    width: 90
                },
                {
                    align: 'right',
                    format: {type: 'resolution', args: ['px']},
                    id: 'resolution',
                    operator: '-',
                    title: Ox._('Resolution'),
                    visible: true,
                    width: 112
                },
                {
                    align: 'right',
                    format: function(value) {
                        value = value.split(':').map(function(v) {
                            return Math.round(v);
                        });
                        return (value[1] != 1
                            ? Ox.formatNumber(value[0] / (value[1] || 1), 2)
                            : value[0]
                        ) + ' fps';
                    },
                    id: 'framerate',
                    operator: '-',
                    title: Ox._('Framerate'),
                    visible: true,
                    width: 70
                },
                {
                    align: 'right',
                    format: {type: 'duration', args: [0, 'short']},
                    id: 'duration',
                    operator: '-',
                    title: Ox._('Duration'),
                    visible: true,
                    width: 90
                },
                {
                    align: 'left',
                    id: 'id',
                    operator: '+',
                    title: Ox._('ID'),
                    visible: false,
                    width: 128
                },
                {
                    align: 'left',
                    id: 'instances',
                    operator: '+',
                    title: Ox._('Instances'),
                    visible: false,
                    width: 120
                }
            ],
            columnsMovable: true,
            columnsRemovable: true,
            columnsResizable: true,
            columnsVisible: true,
            id: 'files',
            items: function(data, callback) {
                pandora.api.findMedia(Ox.extend(data, {
                    query: self.filesQuery
                }), callback);
            },
            keys: ['state', 'instances', 'wanted', 'error'],
            pageLength: 1000,
            scrollbarVisible: true,
            sort: [{key: 'path', operator: '+'}],
            unique: 'id'
        })
        .bindEvent({
            click: function(data) {
                if (data.key == 'selected') {
                    var value = self.$filesList.value(data.id);
                    if (value.state == 'failed') {
                        var $dialog = Ox.Dialog({
                            buttons: [
                                Ox.Button({
                                    id: 'close',
                                    title: Ox._('Close')
                                })
                                .bindEvent({
                                    click: function() {
                                        $dialog.close();
                                    }
                                })
                            ],
                            closeButton: true,
                            content: $('<code>').append(
                                $('<pre>')
                                    .addClass('OxSelectable')
                                    .css({margin: '16px'})
                                    .text(value.error)
                            ),
                            height: Math.round((window.innerHeight - 48) * 0.9),
                            keys: {enter: 'close', escape: 'close'},
                            maximizeButton: true,
                            removeOnClose: true,
                            title: 'Encoding Failed',
                            width: Math.round(window.innerWidth * 0.9)
                        })
                        .open();
                    } else {
                        var instances = self.$filesList.value(data.id, 'instances'),
                            selected = self.$filesList.value(data.id, 'selected'),
                            ignored = (instances.length == 0 && ! selected) ||
                                instances.filter(function(i) {return i.ignore; }).length > 0;
                        pandora.api.editMedia({
                            files: [{
                                id: data.id,
                                ignore: !ignored
                            }]
                        }, function(result) {
                            Ox.Request.clearCache();
                            self.$filesList.reloadList();
                        });
                    }
                }
            },
            'delete': function(data) {
                var ids = data.ids.filter(function(id) {
                    return self.$filesList.value(id, 'instances').length == 0;
                });
                if (ids.length > 0 && pandora.user.level == 'admin') {
                    pandora.api.removeMedia({
                        ids: ids
                    }, function(result) {
                        Ox.Request.clearCache();
                        self.$filesList.reloadList();
                    });
                }
            },
            init: function(data) {
                self.numberOfItems = data.items;
                updateStatus();
            },
            select: selectFiles,
            open: openVideo,
            submit: function(data) {
                var value = self.$filesList.value(data.id, data.key);
                if (data.value != value && !(data.value === '' && value === null)) {
                    self.$saveButton.options({disabled: false});
                    self.$filesList.value(data.id, data.key, data.value || null);
                }
            }
        });

    self.$instancesList = Ox.TableList({
            columns: [
                {
                    align: 'left',
                    id: 'user',
                    operator: '+',
                    title: Ox._('User'),
                    visible: true,
                    width: 120
                },
                {
                    align: 'left',
                    id: 'volume',
                    operator: '+',
                    title: Ox._('Volume'),
                    visible: true,
                    width: 120
                },
                {
                    align: 'left',
                    id: 'path',
                    operator: '+',
                    title: Ox._('Path'),
                    visible: true,
                    width: 480
                },
            ],
            columnsMovable: true,
            columnsRemovable: true,
            columnsResizable: true,
            columnsVisible: true,
            id: 'files',
            items: [],
            scrollbarVisible: true,
            sort: [{key: 'user', operator: '+'}],
            unique: 'path'
        })
        .bindEvent({
            open: openFiles
        });

    self.$movieLabel = Ox.Label({
            textAlign: 'center',
            title: Ox._('Move selected files to another {0}',
                [Ox._(pandora.site.itemName.singular.toLowerCase())]),
            width: 240
        })
        .css({margin: '8px'});

    keys.forEach(function(key) {
        var itemKey = Ox.getObjectById(pandora.site.itemKeys, key);
        self['$' + key + 'Input'] = Ox.Input({
            label: Ox._(key == 'id' ? 'ID'
                : itemKey ? itemKey.title : Ox.toTitleCase(key)),
            labelWidth: 64,
            width: 240
        })
        .bindEvent({
            change: function(data) {
                var conditions, matches;
                if (key == 'id' && data.value.substr(0, 2) != '0x') {
                    if (pandora.site.site.id == '0xdb') {
                        matches = data.value.match(/\d+/);
                    } else {
                        matches = data.value.match(/[A-Z]+/);
                    }
                    data.value = matches ? matches[0] : '';
                    self.$idInput.value(data.value);
                }
                if (data.value.length) {
                    conditions = {};
                    keys.map(function(key) {
                        var value = self['$' + key + 'Input'].value();
                        if (value.length) {
                            conditions[key] = Ox.contains(listKeys, key) ? value.split(', ') : value;
                        }
                    });
                    pandora.api.findId(conditions, function(result) {
                        var length = result.data.items.length;
                        if (length == 0) {
                            if (key != 'id') {
                                self.$idInput.value('');
                            }
                        } else if (result.data.items.length == 1) {
                            keys.forEach(function(key) {
                                self['$' + key + 'Input'].value(
                                    Ox.contains(listKeys, key)
                                        ? result.data.items[0][key].join(', ')
                                        : result.data.items[0][key]
                                );
                            });
                        } else {
                            self.$idInput.value('');
                        }
                    });
                }
            }
        }).on({
            keyup: updateForm
        });
    });

    self.$switch = Ox.Checkbox({
        title: Ox._('Switch to this {0} after moving files',
            [Ox._(pandora.site.itemName.singular.toLowerCase())]),
        value: false,
        width: 240
    });

    self.$movieForm = Ox.Form({
            items: keys.map(function(key) {
                return self['$' + key + 'Input'];
            }).concat([
                self.$switch
            ]),
            width: 240
        })
        .css({margin: '8px'});

    self.$clearButton = Ox.Button({
            title: Ox._('Clear Form'),
            width: 116
        })
        .css({margin: '0 4px 4px 8px'})
        .bindEvent({
            click: function() {
                keys.forEach(function(key) {
                    self['$' + key + 'Input'].value('');
                });
            }
        });

    self.$moveButton = Ox.Button({
            disabled: true,
            title: Ox._('Move Files'),
            width: 116
        })
        .css({margin: '0 4px 4px 4px'})
        .bindEvent({
            click: moveFiles
        });
    

    self.$moviePanel = Ox.Element()
        .append(self.$movieLabel)
        .append(self.$movieForm)
        .append(self.$clearButton)
        .append(self.$moveButton);

    that.setElement(Ox.SplitPanel({
            elements: [
                {
                    element: Ox.SplitPanel({
                        elements: [
                            {
                                element: self.$toolbar,
                                size: 24
                            },
                            {
                                element: self.$filesList
                            },
                            {
                                element: self.$instancesList,
                                size: 80
                            }
                        ],
                        orientation: 'vertical'
                    })
                },
                {
                    collapsible: true,
                    element: self.$moviePanel,
                    size: 256
                }
            ],
            orientation: 'horizontal'
        })
    );

    function deleteItem(data) {
        pandora.api.get({
            id: pandora.user.ui.item,
            keys: ['id', 'title']
        },function(result) {
            pandora.$ui.deleteItemsDialog = pandora.ui.deleteItemsDialog({
                items: [result.data]
            }).open();
        });
    }

    function ignoreFiles() {
        pandora.api.editMedia({
            files: self.selected.map(function(id) {
                return {id: id, ignore: true};
            })
        }, function(result) {
            Ox.Request.clearCache();
            self.$filesList.reloadList();
        });
    }

    function isActive() {
        return pandora.user.ui.item == options.id
            && pandora.user.ui.itemView == 'media';
    }

    function moveFiles(data) {
        var data = {
            ids: self.selected,
        };
        keys.forEach(function(key) {
            data[key == 'id' ? 'item' : key] = Ox.encodeHTMLEntities(self['$' + key + 'Input'].value());
        });
        self.$moveButton.options(
            {disabled: true, title: Ox._('Moving Files...')}
        );
        pandora.api.moveMedia(data, function(result) {
            pandora.wait(result.data.taskId, function(result) {
                if (isActive()) {
                    Ox.Request.clearCache(); // fixme: remove
                    if (self.$switch.value()) {
                        pandora.UI.set({item: result.data.item});
                        pandora.updateItemContext();
                    } else {
                        self.$filesList.reloadList();
                        self.$instancesList.reloadList();
                        self.$moveButton.options(
                            {disabled: false, title: Ox._('Move Files')}
                        );
                    }
                }
            });
        });
    }


    function openFiles(data) {
        data.ids.length == 1 && pandora.api.parsePath({
            path: self.$instancesList.value(data.ids[0], 'path')
        }, function(result) {
            self.$idInput.value('');
            keys.forEach(function(key) {
                if (result.data[key]) {
                    self['$' + key + 'Input'].value(
                        Ox.decodeHTMLEntities(Ox.contains(listKeys, key)
                            ? result.data[key].join(', ')
                            : result.data[key]
                    ));
                }
            });
            updateForm();
            self.$titleInput.triggerEvent('change', {value: result.data['title']});
        });
    }

    function openVideo(data) {
        if (data.ids.length == 1) {
            var stream = data.ids[0];
            pandora.api.get({id: pandora.user.ui.item, keys: ['streams', 'durations']}, function(result) {
                var offset = result.data.streams.indexOf(stream),
                    set = {
                        itemView: pandora.user.ui.videoView
                    },
                    videoPoints = {};
                if (offset > -1) {
                    videoPoints['position'] = videoPoints['in'] = Ox.sum(result.data.durations.slice(0, offset));
                    videoPoints['out'] = videoPoints['in'] + result.data.durations[offset];
                    set['videoPoints.' + pandora.user.ui.item] = videoPoints;
                    pandora.UI.set(set);
                }
            });
        }
    }

    function selectFiles(data) {
        self.selected = data.ids;
        self.$instancesList.options({
            items: Ox.flatten(data.ids.map(function(id) {
                return self.$filesList.value(id, 'instances');
            }))
        });
        updateForm();
    }

    function saveChanges() {
        self.$saveButton.options({disabled: true, title: Ox._('Saving Changes...')});
        pandora.api.findMedia({
            keys: ['id'],
            query: self.filesQuery
        }, function(result) {
            pandora.api.editMedia({
                files: result.data.items.map(function(item) {
                    [
                        'version', 'part', 'partTitle', 'language', 'extension'
                    ].forEach(function(key) {
                        Ox.extend(item, key, self.$filesList.value(item.id, key));
                    })
                    return item;
                })
            }, function(result) {
                self.$saveButton.options({title: Ox._('Save Changes')});
                Ox.Request.clearCache(); // fixme: remove
                self.$filesList.reloadList();
            });
        });
    }

    function updateForm() {
        if (pandora.site.itemRequiresVideo && self.selected.length == self.numberOfItems) {
            self.wasChecked = self.$switch.value();
            self.$switch.options({
                disabled: true,
                value: true
            });
        } else {
            self.$switch.options({
                disabled: false,
                value: self.wasChecked
            });
        }
        self.$moveButton.options({
            disabled: self.selected.length == 0 || (
                self.$idInput.value().length + self.$titleInput.value().length
            ) == 0
        });
        self.$menu[
            self.selected.length == 0 ? 'disableItem' : 'enableItem'
        ]('ignore');
    }

    function updateStatus() {
        if (self.numberOfItems) {
            setTimeout(function() {
                if (isActive() && self.numberOfItems) {
                    Ox.Request.clearCache();
                    pandora.api.findMedia({
                        query: self.filesQuery,
                        range: [0, self.numberOfItems],
                        keys: ['id', 'state']
                    }, function(result) {
                        if (isActive()) {
                            var done = false,
                                update = false;
                            result.data.items.forEach(function(item) {
                                if (self.$filesList.value(item.id, 'state') == 'encoding'
                                    && item.state != 'encoding') {
                                    self.$filesList.value(item.id, 'state', item.state);
                                    done = true;
                                }
                                if (!update && item.state == 'encoding') {
                                    update = true;
                                }
                            });
                            if (update) {
                                updateStatus();
                            } else if (done) {
                                Ox.Request.clearCache();
                                pandora.updateItemContext();
                                pandora.$ui.info && pandora.$ui.info.updateInfo();
                                pandora.$ui.mainPanel.replaceElement(1,
                                    pandora.$ui.rightPanel = pandora.ui.rightPanel());
                            }
                        }
                    });
                }
            }, 10000);
        }
    }

    that.reload = function() {
        self.$filesList.reloadList();
    }
    return that;

};
