<?php $this->layout('main', ['title' => __('Music Files'), 'manual' => true, 'page_class' => 'page-file-manager']) ?>

<?php
/** @var \App\Assets $assets */
$assets
    ->load('vue')
    ->load('radio')
    ->load('bootgrid')
    ->load('moment')
    ->addJs([
        'src' => 'https://cdnjs.cloudflare.com/ajax/libs/flow.js/2.13.0/flow.min.js',
        'sri' => 'sha256-F82/auvnDa23QdME+MJ76ucrjnWyUDxKwEvCuhT1m2Y=',
    ], 'header');
?>

<div class="row">
    <div class="col-sm-12">
        <div class="card">
            <div class="card-header ch-alt">
                <div class="row">
                    <div class="col-md-8">
                        <h2><?=__('Music Files') ?></h2>
                        <div id="breadcrumb" class="">&nbsp;</div>
                    </div>
                    <div class="col-md-4 text-right">
                        <div class="progress">
                            <div class="progress-bar" role="progressbar" aria-valuenow="<?=$space_percent ?>" aria-valuemin="0" aria-valuemax="100" style="width: <?=$space_percent ?>%;">
                                <span class="sr-only"><?=$space_percent ?>%</span>
                            </div>
                        </div>
                        <?=sprintf(__('%s of %s Used (%s Free)'), $space_used, $space_total, $space_free) ?>
                    </div>
                </div>
            </div>

            <div class="card-body card-padding-sm">

                <?php if (APP_INSIDE_DOCKER): ?>
                    <p><i class="zmdi zmdi-info"></i> <?=sprintf(__('You can also upload files in bulk via SFTP by <a href="%s" target="_blank">following these instructions</a>. Newly uploaded files will automatically be processed within a few minutes.'), 'https://github.com/AzuraCast/AzuraCast/blob/master/SUPPORT.md#access-files-via-sftp-docker-installations') ?></p>
                <?php endif; ?>

                <div id="upload_progress"></div>
                <div id="file_drop_target">
                    <?=__('Drag files here to upload to this folder or ') ?>
                    <input id="file_browse_target" type="file" accept=".mp3,.ogg,.wav,.aac,.mp4,.m4a,audio/*" multiple />
                </div>

                <div class="row p-t-20" id="app-toolbar">
                    <div class="col-sm-8">
                        <?=__('With selected:') ?>&nbsp;
                        <div class="btn-group">
                            <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
                                <i class="zmdi zmdi-playlist-plus"></i> <?=__('Add to Playlist') ?>
                                <span class="caret"></span>
                            </button>
                            <ul class="dropdown-menu" role="menu">
                                <li v-for="playlist in playlists">
                                    <a href="#" class="btn-batch" v-on:click="doBatch" v-bind:data-action="'playlist_' + playlist.id">{{ playlist.name }}</a>
                                </li>
                                <li><a href="#" class="btn-new-playlist" data-toggle="modal" data-target="#mdl-create-playlist"><?=__('Create new...') ?></a></li>
                            </ul>
                        </div>
                        <button type="button" class="btn btn-warning" v-on:click="doBatch" data-action="clear"><i class="zmdi zmdi-playlist-audio"></i> <?=__('Clear Playlists') ?></button>
                        <button type="button" class="btn btn-danger" v-on:click="doBatch" data-action="delete"><i class="zmdi zmdi-delete"></i> <?=__('Delete') ?></button>
                    </div>
                    <div class="col-sm-4 text-right">
                        <a class="btn btn-default" href="#" data-toggle="modal" data-target="#mdl-create-directory"><i class="zmdi zmdi-folder"></i> <?=__('New Folder') ?></a>
                    </div>
                </div>
            </div>
            <div class="table-responsive">
                <table class="data-table table table-striped" id="file-table">
                    <thead>
                        <tr>
                            <th data-column-id="name" data-formatter="playable" data-identifier="true"><?=__('Name') ?></th>
                            <th data-column-id="media_title" data-visible="false"><?=__('Title') ?></th>
                            <th data-column-id="media_artist" data-visible="false"><?=__('Artist') ?></th>
                            <th data-column-id="media_album" data-visible="false"><?=__('Album') ?></th>
                            <th data-column-id="media_length" data-formatter="file_length"><?=__('Length') ?></th>
                        <?php foreach($custom_fields as $field_key => $field_label): ?>
                            <th data-column-id="<?=$field_key ?>" data-visible="false"><?=$this->e($field_label) ?></th>
                        <?php endforeach; ?>
                            <th data-column-id="size" data-formatter="file_size"><?=__('Size') ?></th>
                            <th data-column-id="mtime" data-formatter="file_mtime"><?=__('Modified') ?></th>
                            <th data-column-id="media_playlists" data-formatter="playlists"><?=__('Playlists') ?></th>
                            <th data-column-id="commands" data-formatter="commands" data-sortable="false"><?=__('Actions') ?></th>
                        </tr>
                    </thead>
                    <tbody></tbody>
                </table>
            </div>
        </div>
    </div>
</div>

<div class="modal fade" id="mdl-create-playlist" tabindex="-1" role="dialog">
    <div class="modal-dialog" role="document">
        <form id="frm-create-playlist">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                    <h4 class="modal-title" id="exampleModalLabel"><?=__('Create Playlist') ?></h4>
                </div>
                <div class="modal-body">
                    <div class="form-group">
                        <label for="name" class="control-label"><?=__('Playlist Name') ?>:</label>
                        <input type="text" class="form-control" id="fld-playlist-name" name="name">
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                    <button type="submit" id="btn-create-new-playlist" class="btn btn-primary"><?=__('Create Playlist') ?></button>
                </div>
            </div>
        </form>
    </div>
</div>

<div class="modal fade" id="mdl-create-directory" tabindex="-1" role="dialog">
    <div class="modal-dialog" role="document">
        <form id="frm-create-directory">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                    <h4 class="modal-title" id="exampleModalLabel"><?=__('New Directory') ?></h4>
                </div>
                <div class="modal-body">
                    <div class="form-group">
                        <label for="name" class="control-label"><?=__('Directory Name') ?>:</label>
                        <input type="text" class="form-control" id="fld-directory-name" name="name">
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                    <button type="submit" id="btn-create-new-playlist" class="btn btn-primary"><?=__('Create Directory') ?></button>
                </div>
            </div>
        </form>
    </div>
</div>

<script type="text/javascript" nonce="<?=$assets->getCspNonce() ?>">
$(function() {
    var CSRF = '<?=$csrf ?>';
    var MAX_UPLOAD_SIZE = <?=$max_upload_size ?>;

    var $current_dir = '';

    var appToolbar = new Vue({
        el: '#app-toolbar',
        data: {
            playlists: <?=json_encode($playlists) ?>
        },
        methods: {
            doBatch: function (e) {
                e.preventDefault();

                var $files = getSelectedFiles();
                $files.length && $.post('<?=$router->fromHere('stations:files:batch') ?>',{
                    'do': $(e.target).data('action'),
                    'files': $files.join('|'),
                    'csrf': CSRF,
                    'file': getUrlHash()
                },function(data){
                    list();
                },'json');

                $(this).closest('.btn-group').removeClass('open');
                return false;
            }
        }
    });

    var grid = $("#file-table").bootgrid({
        ajax: true,
        selection: true,
        multiSelect: true,
        rowSelect: false,
        caseSensitive: false,
        css: {
            icon: 'zmdi icon',
            iconColumns: 'zmdi-view-module',
            iconDown: 'zmdi-sort-amount-desc',
            iconRefresh: 'zmdi-refresh',
            iconUp: 'zmdi-sort-amount-asc'
        },
        url: "<?=$router->fromHere('stations:files:list')  ?>",
        post: function() {
            return {
                'file': $current_dir,
                'csrf': CSRF
            };
        },
        formatters: {
            "playable": function(column, row) {
                var $url = row.is_dir ? '#' + row.path : row.media_play_url;
                var $icon = '';

                if (row.media_is_playable)
                    $icon = '<a class="file-icon btn-audio" href="#" data-url="'+$url+'"><i class="zmdi zmdi-play"></i></a>';
                else
                    $icon = '<span class="file-icon"><i class="zmdi zmdi-'+(row.is_dir ? 'folder' : 'file')+'"></i></span>';

                var $link = '<a class="name" href="'+$url+'" title="'+row.name+'">'+(row.is_dir ? row.text : row.media_name)+'</a>';

                var art_src = (row.media_art) ? row.media_art : '/static/img/generic_song.jpg';
                var $art = (row.is_dir) ? '' : '<a href="'+art_src+'" target="_blank" class="pull-right p-l-10"><img style="width: 40px; height: auto; border-radius: 5px;" alt="<?=__('Album Artwork') ?>" src="'+art_src+'"></a>';

                return '<div class="'+(row.is_dir ? 'is_dir' : 'is_file')+'">'+$art+$icon + $link + '<br><small>'+(row.is_dir ? 'Directory' : row.text)+'</small></div>';
            },
            "commands": function(column, row) {
                if (row.media_edit_url)
                    return '<a class="btn btn-sm btn-primary" href="'+row.media_edit_url+'"><?=__('Edit') ?></a>';
                else
                    return '<a class="btn btn-sm btn-primary" href="'+row.rename_url+'"><?=__('Rename') ?></a>';
            },
            "file_length": function(column, row) {
                if (row.media_length_text)
                    return row.media_length_text;
                else
                    return 'N/A';
            },
            "file_size": function(column, row) {
                return formatFileSize(row.size);
            },
            "file_mtime": function(column, row) {
                return formatTimestamp(row.mtime);
            },
            "playlists": function(column, row) {
                if (row.media_playlists.length > 0) {
                    var playlists = [];
                    var playlist;

                    for (var i = 0; i < row.media_playlists.length; i++) {
                        playlist = row.media_playlists[i];
                        playlists.push('<a class="btn-search" href="#" data-term="playlist:'+playlist+'">'+playlist+'</a>');
                    }

                    return playlists.join(', ');
                } else {
                    return '';
                }
            }
        }
    }).on("loaded.rs.jquery.bootgrid", function() {
        /* Executes after data is loaded and rendered */
        grid.find(".btn-audio").on("click", function(e) {
            e.preventDefault();
            handlePlayClick($(this).data('url'));
            return false;
        });

        /* Handle playlist search function */
        grid.find(".btn-search").on("click", function(e) {
            e.preventDefault();
            grid.bootgrid("clear").bootgrid("search", $(this).data('term'));
            return false;
        });
    });

    // Check if initial URL has a hash.
    var hashval = getUrlHash();

    if (hashval.length > 0)
        list();
    else
        $('#breadcrumb').empty().html(renderBreadcrumbs(hashval));

    $(window).bind('hashchange',list);

    // Create new directory
    $('form#mkdir').submit(function(e) {
        e.preventDefault();

        var hashval = getUrlHash();
        var $dir = $(this).find('[name=name]');

        $dir.val().length && $.post('<?=$router->fromHere('stations:files:mkdir') ?>',{
            name: $dir.val(),
            csrf: CSRF,
            file: hashval
        },function(data){
            list();
        },'json');

        $dir.val('');
        return false;
    });

    $('.btn-new-playlist').on('click', function(e) {
        $(this).closest('.btn-group').removeClass('open');
    });

    $('#frm-create-playlist').submit(function(e) {
        e.preventDefault();

        var $files = getSelectedFiles();
        $files.length && $.post('<?=$router->fromHere('stations:files:batch') ?>',{
            'do': 'playlist_new',
            'name': $('#fld-playlist-name').val(),
            'files': $files.join('|'),
            'csrf': CSRF,
            'file': getUrlHash()
        },function(data){
            if (data.success) {
                appToolbar.playlists.push(data.record);
            }
            list();
        },'json');

        $('#fld-playlist-name').val('');
        $('#mdl-create-playlist').modal('hide');

        return false;
    });

    $('#frm-create-directory').submit(function(e) {
        e.preventDefault();

        var $dir = $('#fld-directory-name');

        $dir.val().length && $.post('<?=$router->fromHere('stations:files:mkdir') ?>',{
            name: $dir.val(),
            csrf: CSRF,
            file: getUrlHash()
        },function(data){
            list();
        },'json');

        $dir.val('');
        $('#mdl-create-directory').modal('hide');
        return false;
    });

    // File upload stuff
    var flow = new Flow({
        target: '<?=$router->fromHere('stations:files:upload') ?>',
        query: function() {
            return {
                csrf: CSRF,
                file: getUrlHash()
            };
        },
        withCredentials: true,
        allowDuplicateUploads: true,
        fileParameterName: 'file_data'
    });

    flow.assignBrowse(document.getElementById('file_browse_target'));
    flow.assignDrop(document.getElementById('file_drop_target'));

    flow.on('fileAdded', function(file, event) {
        $('#upload_progress').append(renderFileUploadRow(file));
        return true;
    });
    flow.on('filesSubmitted', function(array, event) {
        flow.upload();
    });
    flow.on('fileProgress', function(file) {
        var $row = $('#file_upload_'+file.uniqueIdentifier);
        $row.find('.progress-bar').css('width',(file.progress() * 100)+'%' );
    });
    flow.on('fileSuccess', function(file, message){
        var $row = $('#file_upload_'+file.uniqueIdentifier);
        $row.fadeOut();
        list();
    });
    flow.on('fileError', function(file, message){
        var $row = $('#file_upload_'+file.uniqueIdentifier);
        $row.remove();

        var $error_row = renderFileSizeErrorRow(file, message);
        $('#upload_progress').append($error_row);
        window.setTimeout(function(){ $error_row.fadeOut(); },5000);
    });
    flow.on('error', function(message, file, chunk) {
        console.log(message, file, chunk);
    });

    function renderFileUploadRow(file) {
        return $row = $('<div id="file_upload_'+file.uniqueIdentifier+'"/>')
            .append( $('<span class="fileuploadname" />').text(file.name) )
            .append( $('<div class="progress"><div class="progress-bar"></div></div>') )
            .append( $('<span class="size" />').text(formatFileSize(file.size)) );
    }

    function renderFileSizeErrorRow(file, message) {
        return $row = $('<div id="file_upload_error_'+file.uniqueIdentifier+'" class="error" />')
            .append( $('<span class="fileuploadname" />').text('Error: ' + file.name))
            .append( $('<span/>').text(message) );
    }

    function list() {
        var hashval = getUrlHash();
        $('#breadcrumb').empty().html(renderBreadcrumbs(hashval));

        console.log('Relisting for directory: #'+hashval);

        $current_dir = hashval;
        $('#file-table').bootgrid("reload");
    }

    function getUrlHash()
    {
        var url_hash = decodeURIComponent(window.location.hash.substr(1).replace(/\+/g, "%20"));

        if (url_hash.substr(0, 9) === 'playlist:') {
            window.location.hash = '';
            grid.bootgrid("clear").bootgrid("search", url_hash);
            return '';
        }

        return url_hash;
    }

    function getSelectedFiles()
    {
        $files = [];
        $('#file-table').find('tr.active').each(function() {
            $files.push($(this).data('row-id'));
        });

        console.log($files);
        return $files;
    }

    function renderBreadcrumbs(path) {
        var base = "",
            $html = $('<div/>').append( $('<a href=#>Home</a></div>') );
        $.each(path.split('/'),function(k,v){
            if(v) {
                $html.append( $('<span/>').text(' ▸ ') )
                    .append( $('<a/>').attr('href','#'+base+v).text(v) );
                base += v + '/';
            }
        });
        return $html;
    }

    function formatTimestamp(unix_timestamp) {
        return moment.unix(unix_timestamp).format('lll');
    }

    function formatFileSize(bytes) {
        var s = ['bytes', 'KB','MB','GB','TB','PB','EB'];
        for(var pos = 0;bytes >= 1000; pos++,bytes /= 1024);
        var d = Math.round(bytes*10);
        return pos ? [parseInt(d/10),".",d%10," ",s[pos]].join('') : bytes + ' bytes';
    }
})
</script>
