text: 'use strict';
  
  // based on http://www.compix.com/fileformattif.htm
  // TO-DO: support big-endian as well
  
  var fs = require('fs');
  var readUInt = require('../readUInt');
  
  function isTIFF (buffer) {
    var hex4 = buffer.toString('hex', 0, 4);
    return ('49492a00' === hex4 || '4d4d002a' === hex4);
  }
  
  // Read IFD (image-file-directory) into a buffer
  function readIFD (buffer, filepath, isBigEndian) {
  
    var ifdOffset = readUInt(buffer, 32, 4, isBigEndian);
  
    // read only till the end of the file
    var bufferSize = 1024;
    var fileSize = fs.statSync(filepath).size;
    if (ifdOffset + bufferSize > fileSize) {
      bufferSize = fileSize - ifdOffset - 10;
    }
  
    // populate the buffer
    var endBuffer = new Buffer(bufferSize);
    var descriptor = fs.openSync(filepath, 'r');
    fs.readSync(descriptor, endBuffer, 0, bufferSize, ifdOffset);
  
    // var ifdLength = readUInt(endBuffer, 16, 0, isBigEndian);
    var ifdBuffer = endBuffer.slice(2); //, 2 + 12 * ifdLength);
    return ifdBuffer;
  }
  
  // TIFF values seem to be messed up on Big-Endian, this helps
  function readValue (buffer, isBigEndian) {
    var low = readUInt(buffer, 16, 8, isBigEndian);
    var high = readUInt(buffer, 16, 10, isBigEndian);
    return (high << 16) + low;
  }
  
  // move to the next tag
  function nextTag (buffer) {
    if (buffer.length > 24) {
      return buffer.slice(12);
    }
  }
  
  // Extract IFD tags from TIFF metadata
  function extractTags (buffer, isBigEndian) {
    var tags = {};
    var code, type, length;
  
    while (buffer && buffer.length) {
      code = readUInt(buffer, 16, 0, isBigEndian);
      type = readUInt(buffer, 16, 2, isBigEndian);
      length = readUInt(buffer, 32, 4, isBigEndian);
  
      // 0 means end of IFD
      if (code === 0) {
        break;
      } else {
        // 256 is width, 257 is height
        // if (code === 256 || code === 257) {
        if (length === 1 && (type === 3 || type === 4)) {
          tags[code] = readValue(buffer, isBigEndian);
        }
  
        // move to the next tag
        buffer = nextTag(buffer);
      }
    }
    return tags;
  }
  
  // Test if the TIFF is Big Endian or Little Endian
  function determineEndianness (buffer) {
    var signature = buffer.toString('ascii', 0, 2);
    if ('II' === signature) {
      return 'LE';
    } else if ('MM' === signature) {
      return 'BE';
    }
  }
  
  function calculate (buffer, filepath) {
  
    if (!filepath) {
      throw new TypeError('Tiff doesn\'t support buffer');
    }
  
    // Determine BE/LE
    var isBigEndian = determineEndianness(buffer) === 'BE';
  
    // read the IFD
    var ifdBuffer = readIFD(buffer, filepath, isBigEndian);
  
    // extract the tags from the IFD
    var tags = extractTags(ifdBuffer, isBigEndian);
  
    var width = tags[256];
    var height = tags[257];
  
    if (!width || !height) {
      throw new TypeError('Invalid Tiff, missing tags');
    }
  
    return {
      'width': width,
      'height': height
    };
  }
  
  module.exports = {
    'detect': isTIFF,
    'calculate': calculate
  };
  