import JSONSerializer from 'ember-data/serializers/json';
import { underscore } from 'ember-string';
import { normalizeVideoId } from 'web-client/utilities/normalize-video-id';
import { isEmberArray } from 'ember-array/utils';

const IMAGE_404 = /\/404_processing_/;

export default JSONSerializer.extend({
  keyForAttribute: function(attr) {
    if (this.attrs.hasOwnProperty(attr) && this.attrs[attr].hasOwnProperty('key')) {
      return this.attrs[attr].key;
    }
    return underscore(attr);
  },

  attrs: {
    descriptionHTML: { serialize: false },
    descriptionMarkdown: { key: 'description' },
    type: { key: 'broadcast_type' }
  },

  extractAttributes(model, payload) {
    let attributes = this._super(model, payload);

    // The server always returns preview URLs for videos, even when there are
    // no images present. When fetched these placeholder URLs return server
    // errors, not images.
    //
    // Here we detect whether we have valid image URLs or just placeholders.
    // If these are placeholder URLs we don't set them on the model. This way
    // we can avoid accidentally using them in our templates.
    if (has404URLs(attributes.preview)) {
      attributes.preview = {};
    }

    // Add channelName from nested channel object.
    let channelName = payload.channel && payload.channel.name;
    if (channelName) {
      attributes.channelName = channelName;
    }

    // In order to use this model with search results, skip this logic if thumbnails isn't set.
    // Search results will have a singular thumbnail field that is handled below
    if (attributes.thumbnails) {
      // Backend will eventually not return multiple thumbnails sizes here.
      if (!isEmberArray(attributes.thumbnails)) {
        attributes.thumbnails = attributes.thumbnails.medium;
      }

      // Backend will eventually make our PUT endpoint respect v4 api thumbnail sizes.
      attributes.thumbnails = attributes.thumbnails.map((thumbnail) => {
        if(thumbnail.url.indexOf('320x240') !== -1) {
          thumbnail.url = thumbnail.url.replace('320x240', '320x180');
        }

        return thumbnail;
      });

      // We always reset `deleteCustomThumbnail` to be false after a request.
      attributes.deleteCustomThumbnail = false;

      let thumbnail = attributes.thumbnails.findBy('url', attributes.preview.medium);
      let thumbnailIndex = attributes.thumbnails.indexOf(thumbnail);

      // We provide a default value for thumbnailIndex with our initial POST request
      // `thumbnailIndex` will remain null.
      if (thumbnailIndex !== -1) {
        attributes.thumbnailIndex = thumbnailIndex;
      }
    }

    // Map our search result version of preview across
     if (!attributes.preview && payload.thumbnail) {
       attributes.preview = payload.thumbnail;
     }

    return attributes;
  },

  extractId(model, video) {
    // objectID is the video search result ID
    let id = video._id || video.objectID;
    return normalizeVideoId(id);
  },

  extractRelationships(modelClass, resourceHash){
    let relationships = {};

    let channelName;
    if (resourceHash.channel) {
      channelName = resourceHash.channel.name;
    } else {
      // Video Search Result format
      channelName = resourceHash.broadcaster_login;
    }

    relationships.channel = {
      data: { type: 'channel', id: channelName }
    };

    return relationships;
  },

  normalizeUpdateRecordResponse(store, primaryModelClass, payload, id) {
    let attributes = this.extractAttributes(primaryModelClass, payload);
    this.applyTransforms(primaryModelClass, attributes);

    return {
      data: {
        id: id,
        type: primaryModelClass.modelName,
        attributes
      }
    };
  },

  normalizeDeleteRecordResponse() {
    // Avoid setting attributes from 200 response
    return { data: null };
  },

  normalizeSearchResult(searchVideo) {
    let videoModel = this.normalizeSingleResponse(
      this.store,
      this.store.modelFor('video'),
      searchVideo,
      searchVideo.objectID
    );

    return this.store.push(videoModel);
  },

  serializeForCreate(snapshot) {
    return this.serialize(snapshot);
  },

  serializeForUpdate(snapshot) {
    let result = this.serialize(snapshot);
    delete result.channel;
    return result;
  }
});

function has404URLs(thumbnails) {
  return thumbnails && IMAGE_404.test(thumbnails.small);
}
