<Service ref:Uploads
  service="Uploads"
  on:update="refresh()"
  on:complete="_onUploadComplete(event)"
  />

<svg style="position: absolute; width: 0; height: 0; overflow: hidden" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <symbol id="icon-upload" viewBox="0 0 32 32">
    <title>upload</title>
    <path d="M30.038 19.938c-0.706 0-1.275 0.569-1.275 1.275v7.544h-25.525v-7.544c0-0.706-0.569-1.275-1.275-1.275s-1.275 0.569-1.275 1.275v8.825c0 0.706 0.569 1.275 1.275 1.275h28.075c0.706 0 1.275-0.569 1.275-1.275v-8.825c0-0.706-0.569-1.275-1.275-1.275z"></path>
    <path d="M9.137 10.625l5.588-5.581v16.194c0 0.706 0.569 1.275 1.275 1.275s1.275-0.569 1.275-1.275v-16.194l5.587 5.581c0.769 0.713 1.556 0.25 1.806 0 0.5-0.5 0.5-1.306 0-1.806l-7.769-7.756c-0.5-0.5-1.306-0.5-1.806 0l-7.756 7.756c-0.5 0.5-0.5 1.306 0 1.806 0.494 0.5 1.306 0.5 1.8 0z"></path>
  </symbol>
  <symbol id="icon-error" viewBox="0 0 21.9 21.9">
    <title>error</title>
    <path d="M14.1 11.3c-.2-.2-.2-.5 0-.7l7.5-7.5c.2-.2.3-.5.3-.7s-.1-.5-.3-.7L20.2.3c-.2-.2-.5-.3-.7-.3-.3 0-.5.1-.7.3l-7.5 7.5c-.2.2-.5.2-.7 0L3.1.3C2.9.1 2.6 0 2.4 0s-.5.1-.7.3L.3 1.7c-.2.2-.3.5-.3.7s.1.5.3.7l7.5 7.5c.2.2.2.5 0 .7L.3 18.8c-.2.2-.3.5-.3.7s.1.5.3.7l1.4 1.4c.2.2.5.3.7.3s.5-.1.7-.3l7.5-7.5c.2-.2.5-.2.7 0l7.5 7.5c.2.2.5.3.7.3s.5-.1.7-.3l1.4-1.4c.2-.2.3-.5.3-.7s-.1-.5-.3-.7l-7.5-7.5z" fill="#de2618"/>
  </symbol>
</svg>

{{#if !loading}}
  {{#if error}}
    <div class="error-panel">
      <h2 class="blogvio-browser-title">Failed to load uploaded files.</h2>
      <p>{{ error.message }}</p>
      <a href="#" on:click="refresh( event )">Click here to try again</a><br/>
      <span>or <a href="mailto:support@widgetic.com">contact support</a> if the error persists.</span>
    </div>
  {{else}}
    <div class="browser-nav">
      {{#if deleteMode}}
        <div class="browser-logout" data-tooltip-text="Delete Selected Files" data-icon="✓" on:click="deleteSelected()"></div>
        <div class="browser-logout" data-tooltip-text="Cancel Selection" data-icon="x" on:click="set({ deleteMode: false, selectedForDeletion: [] })"></div>
        {{#if selectedForDeletion.length}}
          <span>{{selectedForDeletion.length}} files selected for deletion</span>
        {{else}}
          <span>Select files to be deleted</span>
        {{/if}}
      {{else}}
        <div class="browser-logout" data-tooltip-text="Toggle Delete Mode" data-icon="⏍" on:click="set({ deleteMode: true })"></div>
      {{/if}}
    </div>
    <section class="{{ dragging ? 'dropzone--dragging' : '' }}">
      {{#if files.length}}
        <ScrollPane ref:scrollPane>
          {{#each files as file}}
            <File
              file="{{file}}"
              on:select="toggle( event )"
              selected="{{ isSelected(file.id, deleteMode, selected, selectedForDeletion) }}"
              selectedIcon="{{ deleteMode ? 'delete' : 'check' }}">
            </File>
          {{/each}}
        </ScrollPane>
      {{else}}
        <div class="error-panel" style="height: 100%">
          <h2 class="blogvio-browser-title">Hey there!</h2>
          <h3>You haven't uploaded any {{ filetypes }} files yet.</h3>
          <span>Drag some over or click below!</span>
        </div>
      {{/if}}

      <div class="dropzone_plchldr {{ !files.length ? 'dropzone--large' : '' }}">
        <Dropzone
          ref:dropzone
          on:new="_onNewUpload()"
          on:dragging="set({ dragging: event })"
          on:upload="toggle( event )"
          on:error="fire( 'error', event )"
          filetypes="{{ filetypes }}/*"
          maxFilesize="{{ maxFilesize }}"
          instanceId="{{ instanceId }}"
          ></Dropzone>
      </div>
    </section>
  {{/if}}
{{/if}}

<style>
  section {
    display: flex;
    flex-direction: column;
    padding-left: 20px;
    height: calc(100% - 25px);
    color: #665b68;
  }

  a:focus {
    outline: none;
  }

  .error-panel {
    position: relative;
    top: 50%;
    transform: translateY(-50%);
    text-align: center;
    padding-right: 20px;
  }

  .browser-nav {
    position: static;

    font-family: ProximaNova-Regular;
    font-size: 16px;
    color: #ec574d;
  }

  .blogvio-browser-title {
    margin-top: 0;
    font: 30px/60px "ProximaNova-Regular";
    color: #ec574d;
  }

  .nano {
    flex: 1;
  }

  strong {
    color: #ec574d;
  }

  .dropzone_plchldr {
    position: relative;
    margin: 20px 20px 20px 0;
    height: 75px;
  }

  .dropzone {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
  }

  .scrolling-container {
    transition: opacity 200ms ease-in;
  }

  .dropzone--dragging .scrolling-container {
    opacity: 0.4;
  }

  .dropzone--dragging .dropzone {
    top: -100px;
  }

  .dropzone--large .dropzone,
  .dropzone--dragging .dropzone--large .dropzone {
    top: -200px;
  }

  .icon {
    display: inline-block;
    width: 1em;
    height: 1em;
    stroke-width: 0;
    stroke: currentColor;
    fill: currentColor
  }
</style>

<script>
import Dropzone from './dropzone.html';
import ScrollPane from './scroll-pane.html';
import File from './file.html';
import Service from './service.html';

let instanceId = 0;

export default {
  components: { ScrollPane, Dropzone, File, Service },

  data() {
    return {
      instanceId: ++instanceId,
      loading: true,
      error: null,
      files: [],
      dragging: false,
      filetypes: '*',
      deleteMode: false,
      selected: [],
      selectedForDeletion: [],
      maxFilesize: 10,
    };
  },

  helpers: {
    isSelected(id, deleteMode, selected, selectedForDeletion) {
      return deleteMode
        ? selectedForDeletion.includes(id)
        : selected.includes(id);
    },
  },

  oncreate() {
    this.Uploads = this.refs.Uploads.instance();
    this.set({ maxFilesize: this.Uploads.getMaxFileSize() });
    this.refresh();
  },
  ondestroy() {
    this.observer.cancel();
  },

  methods: {
    toggle(file) {
      if (file.error) {
        this.Uploads.remove(file);
        return this.refresh();
      }

      this.get('deleteMode')
        ? this._toggleDelete(file)
        : this._toggleSelect(file);
    },

    activate() {
      if (!this.refs.scrollPane) return;
      this.refs.scrollPane.update();
    },

    refresh(ev) {
      if (ev) ev.preventDefault();

      return this.Uploads
        .getFiles(this.get('filetypes'))
        .then(files => this.set({ files }))
        .then(this.activate.bind(this))
        .catch(this._reportError.bind(this))
        .then(_ => this.set({ loading: false, error: null }));
    },

    deleteSelected() {
      const selected = this.get('selected');
      this.get('selectedForDeletion').forEach(id => {
        const file = this.Uploads.get(id);
        if (selected.includes(id)) this._toggleSelect(file);
        this.Uploads.remove(file);
      });
      this.set({ deleteMode: false, selectedForDeletion: [] });
    },

    /**
     * options { afterUpload: boolean }
     */
    _toggleSelect(file, options) {
      this.fire('toggle', { file, options });
    },

    _toggleDelete(file) {
      let selectedForDeletion = this.get('selectedForDeletion');

      if (selectedForDeletion.includes(file.id)) {
        selectedForDeletion = selectedForDeletion.filter(id => id !== file.id);
      } else {
        selectedForDeletion.push(file.id);
      }

      this.set({ selectedForDeletion });
    },

    _reportError(error) {
      let processedError = error;

      if (typeof error === 'string') {
        processedError = { message: error };
      }

      if (error.jqXHR) {
        processedError = {
          message: `${error.jqXHR.statusText} (${error.jqXHR.responseText})`,
        };
      }

      console.error(error);
      this.set({ error: processedError });
      this.fire('error', processedError);
    },

    _onNewUpload() {
      this.refs.scrollPane && this.refs.scrollPane.scrollBottom();
    },

    _onUploadComplete([file, instanceId]) {
      // toggle the file only if it's upload originated from this instance
      if (instanceId === this.get('instanceId'))
        this._toggleSelect(file, { afterUpload: true });
    },
  },
};
</script>
