'use strict';

/* eslint-disable no-bitwise */

var ParserStream = require('../common').ParserStream;
var str2arr      = require('../common').str2arr;
var sliceEq      = require('../common').sliceEq;


var SIG_RIFF    = str2arr('RIFF');
var SIG_WEBPVP8 = str2arr('WEBPVP8');


function parseVP8(parser) {
  parser._bytes(14, function (data) {
    parser._skipBytes(Infinity);

    if (data[7] !== 0x9D || data[8] !== 0x01 || data[9] !== 0x2A) {
      // bad code block signature
      parser.push(null);
      return;
    }

    parser.push({
      width:  data.readUInt16LE(10) & 0x3FFF,
      height: data.readUInt16LE(12) & 0x3FFF,
      type:   'webp',
      mime:   'image/webp',
      wUnits: 'px',
      hUnits: 'px'
    });

    parser.push(null);
  });
}


function parseVP8L(parser) {
  parser._bytes(9, function (data) {
    parser._skipBytes(Infinity);

    if (data[4] !== 0x2F) {
      // bad code block signature
      parser.push(null);
      return;
    }

    var bits = data.readUInt32LE(5);

    parser.push({
      width:  (bits & 0x3FFF) + 1,
      height: ((bits >> 14) & 0x3FFF) + 1,
      type:   'webp',
      mime:   'image/webp',
      wUnits: 'px',
      hUnits: 'px'
    });

    parser.push(null);
  });
}


function parseVP8X(parser) {
  parser._bytes(14, function (data) {
    parser._skipBytes(Infinity);

    parser.push({
      // TODO: replace with `data.readUIntLE(8, 3) + 1`
      //       when 0.10 support is dropped
      width:  ((data[10] << 16) | (data[9] << 8) | data[8]) + 1,
      height: ((data[13] << 16) | (data[12] << 8) | data[11]) + 1,
      type:   'webp',
      mime:   'image/webp',
      wUnits: 'px',
      hUnits: 'px'
    });

    parser.push(null);
  });
}


module.exports = function () {
  var parser = new ParserStream();

  parser._bytes(16, function (data) {

    // check /^RIFF....WEBPVP8([ LX])$/ signature

    if (sliceEq(data, 0, SIG_RIFF) && sliceEq(data, 8, SIG_WEBPVP8)) {
      switch (data[15]) {
        case 32/*' '*/: parseVP8(parser); return;
        case 76/* L */: parseVP8L(parser); return;
        case 88/* X */: parseVP8X(parser); return;
      }
    } else {
      parser._skipBytes(Infinity);
      parser.push(null);
    }
  });

  return parser;
};