var path = require( 'path' );
var crypto = require( 'crypto' );

module.exports = {
  createFromFile: function ( filePath, useChecksum ) {
    var fname = path.basename( filePath );
    var dir = path.dirname( filePath );
    return this.create( fname, dir, useChecksum );
  },

  create: function ( cacheId, _path, useChecksum ) {
    var fs = require( 'fs' );
    var flatCache = require( 'flat-cache' );
    var cache = flatCache.load( cacheId, _path );
    var normalizedEntries = { };

    var removeNotFoundFiles = function removeNotFoundFiles() {
      const cachedEntries = cache.keys();
      // remove not found entries
      cachedEntries.forEach( function remover( fPath ) {
        try {
          fs.statSync( fPath );
        } catch (err) {
          if ( err.code === 'ENOENT' ) {
            cache.removeKey( fPath );
          }
        }
      } );
    };

    removeNotFoundFiles();

    return {
      /**
       * the flat cache storage used to persist the metadata of the `files
       * @type {Object}
       */
      cache: cache,

      /**
       * Given a buffer, calculate md5 hash of its content.
       * @method getHash
       * @param  {Buffer} buffer   buffer to calculate hash on
       * @return {String}          content hash digest
       */
      getHash: function ( buffer ) {
        return crypto
          .createHash( 'md5' )
          .update( buffer )
          .digest( 'hex' );
      },

      /**
       * Return whether or not a file has changed since last time reconcile was called.
       * @method hasFileChanged
       * @param  {String}  file  the filepath to check
       * @return {Boolean}       wheter or not the file has changed
       */
      hasFileChanged: function ( file ) {
        return this.getFileDescriptor( file ).changed;
      },

      /**
       * given an array of file paths it return and object with three arrays:
       *  - changedFiles: Files that changed since previous run
       *  - notChangedFiles: Files that haven't change
       *  - notFoundFiles: Files that were not found, probably deleted
       *
       * @param  {Array} files the files to analyze and compare to the previous seen files
       * @return {[type]}       [description]
       */
      analyzeFiles: function ( files ) {
        var me = this;
        files = files || [ ];

        var res = {
          changedFiles: [],
          notFoundFiles: [],
          notChangedFiles: []
        };

        me.normalizeEntries( files ).forEach( function ( entry ) {
          if ( entry.changed ) {
            res.changedFiles.push( entry.key );
            return;
          }
          if ( entry.notFound ) {
            res.notFoundFiles.push( entry.key );
            return;
          }
          res.notChangedFiles.push( entry.key );
        } );
        return res;
      },

      getFileDescriptor: function ( file ) {
        var fstat;

        try {
          fstat = fs.statSync( file );
        } catch (ex) {
          this.removeEntry( file );
          return { key: file, notFound: true, err: ex };
        }

        if ( useChecksum ) {
          return this._getFileDescriptorUsingChecksum( file );
        }

        return this._getFileDescriptorUsingMtimeAndSize( file, fstat );
      },

      _getFileDescriptorUsingMtimeAndSize: function ( file, fstat ) {
        var meta = cache.getKey( file );
        var cacheExists = !!meta;

        var cSize = fstat.size;
        var cTime = fstat.mtime.getTime();

        var isDifferentDate;
        var isDifferentSize;

        if ( !meta ) {
          meta = { size: cSize, mtime: cTime };
        } else {
          isDifferentDate = cTime !== meta.mtime;
          isDifferentSize = cSize !== meta.size;
        }

        var nEntry = normalizedEntries[ file ] = {
          key: file,
          changed: !cacheExists || isDifferentDate || isDifferentSize,
          meta: meta
        };

        return nEntry;
      },

      _getFileDescriptorUsingChecksum: function ( file ) {
        var meta = cache.getKey( file );
        var cacheExists = !!meta;

        var contentBuffer;
        try {
          contentBuffer = fs.readFileSync( file );
        } catch (ex) {
          contentBuffer = '';
        }

        var isDifferent = true;
        var hash = this.getHash( contentBuffer );

        if ( !meta ) {
          meta = { hash: hash };
        } else {
          isDifferent = hash !== meta.hash;
        }

        var nEntry = normalizedEntries[ file ] = {
          key: file,
          changed: !cacheExists || isDifferent,
          meta: meta
        };

        return nEntry;
      },

      /**
       * Return the list o the files that changed compared
       * against the ones stored in the cache
       *
       * @method getUpdated
       * @param files {Array} the array of files to compare against the ones in the cache
       * @returns {Array}
       */
      getUpdatedFiles: function ( files ) {
        var me = this;
        files = files || [ ];

        return me.normalizeEntries( files ).filter( function ( entry ) {
          return entry.changed;
        } ).map( function ( entry ) {
          return entry.key;
        } );
      },

      /**
       * return the list of files
       * @method normalizeEntries
       * @param files
       * @returns {*}
       */
      normalizeEntries: function ( files ) {
        files = files || [ ];

        var me = this;
        var nEntries = files.map( function ( file ) {
          return me.getFileDescriptor( file );
        } );

        //normalizeEntries = nEntries;
        return nEntries;
      },

      /**
       * Remove an entry from the file-entry-cache. Useful to force the file to still be considered
       * modified the next time the process is run
       *
       * @method removeEntry
       * @param entryName
       */
      removeEntry: function ( entryName ) {
        delete normalizedEntries[ entryName ];
        cache.removeKey( entryName );
      },

      /**
       * Delete the cache file from the disk
       * @method deleteCacheFile
       */
      deleteCacheFile: function () {
        cache.removeCacheFile();
      },

      /**
       * remove the cache from the file and clear the memory cache
       */
      destroy: function () {
        normalizedEntries = { };
        cache.destroy();
      },

      _getMetaForFileUsingCheckSum: function ( cacheEntry ) {
        var contentBuffer = fs.readFileSync( cacheEntry.key );
        var hash = this.getHash( contentBuffer );
        var meta = Object.assign( cacheEntry.meta, { hash: hash } );
        return meta;
      },

      _getMetaForFileUsingMtimeAndSize: function ( cacheEntry ) {
        var stat = fs.statSync( cacheEntry.key );
        var meta = Object.assign( cacheEntry.meta, {
          size: stat.size,
          mtime: stat.mtime.getTime()
        } );
        return meta;
      },

      /**
       * Sync the files and persist them to the cache
       * @method reconcile
       */
      reconcile: function ( noPrune ) {
        removeNotFoundFiles();

        noPrune = typeof noPrune === 'undefined' ? true : noPrune;

        var entries = normalizedEntries;
        var keys = Object.keys( entries );

        if ( keys.length === 0 ) {
          return;
        }

        var me = this;

        keys.forEach( function ( entryName ) {
          var cacheEntry = entries[ entryName ];

          try {
            var meta = useChecksum ? me._getMetaForFileUsingCheckSum( cacheEntry ) : me._getMetaForFileUsingMtimeAndSize( cacheEntry );
            cache.setKey( entryName, meta );
          } catch (err) {
            // if the file does not exists we don't save it
            // other errors are just thrown
            if ( err.code !== 'ENOENT' ) {
              throw err;
            }
          }
        } );

        cache.save( noPrune );
      }
    };
  }
};
