text: cordova.define("cordova-plugin-file.FileWriter", function(require, exports, module) {
  /*
   *
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   *
  */
  
  var exec = require('cordova/exec'),
      FileError = require('./FileError'),
      ProgressEvent = require('./ProgressEvent');
  
  /**
   * This class writes to the mobile device file system.
   *
   * For Android:
   *      The root directory is the root of the file system.
   *      To write to the SD card, the file name is "sdcard/my_file.txt"
   *
   * @constructor
   * @param file {File} File object containing file properties
   * @param append if true write to the end of the file, otherwise overwrite the file
   */
  var FileWriter = function(file) {
      this.fileName = "";
      this.length = 0;
      if (file) {
          this.localURL = file.localURL || file;
          this.length = file.size || 0;
      }
      // default is to write at the beginning of the file
      this.position = 0;
  
      this.readyState = 0; // EMPTY
  
      this.result = null;
  
      // Error
      this.error = null;
  
      // Event handlers
      this.onwritestart = null;   // When writing starts
      this.onprogress = null;     // While writing the file, and reporting partial file data
      this.onwrite = null;        // When the write has successfully completed.
      this.onwriteend = null;     // When the request has completed (either in success or failure).
      this.onabort = null;        // When the write has been aborted. For instance, by invoking the abort() method.
      this.onerror = null;        // When the write has failed (see errors).
  };
  
  // States
  FileWriter.INIT = 0;
  FileWriter.WRITING = 1;
  FileWriter.DONE = 2;
  
  /**
   * Abort writing file.
   */
  FileWriter.prototype.abort = function() {
      // check for invalid state
      if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
          throw new FileError(FileError.INVALID_STATE_ERR);
      }
  
      // set error
      this.error = new FileError(FileError.ABORT_ERR);
  
      this.readyState = FileWriter.DONE;
  
      // If abort callback
      if (typeof this.onabort === "function") {
          this.onabort(new ProgressEvent("abort", {"target":this}));
      }
  
      // If write end callback
      if (typeof this.onwriteend === "function") {
          this.onwriteend(new ProgressEvent("writeend", {"target":this}));
      }
  };
  
  /**
   * Writes data to the file
   *
   * @param data text or blob to be written
   */
  FileWriter.prototype.write = function(data) {
  
      var that=this;
      var supportsBinary = (typeof window.Blob !== 'undefined' && typeof window.ArrayBuffer !== 'undefined');
      var isProxySupportBlobNatively = (cordova.platformId === "windows8" || cordova.platformId === "windows");
      var isBinary;
  
      // Check to see if the incoming data is a blob
      if (data instanceof File || (!isProxySupportBlobNatively && supportsBinary && data instanceof Blob)) {
          var fileReader = new FileReader();
          fileReader.onload = function() {
              // Call this method again, with the arraybuffer as argument
              FileWriter.prototype.write.call(that, this.result);
          };
          if (supportsBinary) {
              fileReader.readAsArrayBuffer(data);
          } else {
              fileReader.readAsText(data);
          }
          return;
      }
  
      // Mark data type for safer transport over the binary bridge
      isBinary = supportsBinary && (data instanceof ArrayBuffer);
      if (isBinary && cordova.platformId === "windowsphone") {
          // create a plain array, using the keys from the Uint8Array view so that we can serialize it
          data = Array.apply(null, new Uint8Array(data));
      }
      
      // Throw an exception if we are already writing a file
      if (this.readyState === FileWriter.WRITING) {
          throw new FileError(FileError.INVALID_STATE_ERR);
      }
  
      // WRITING state
      this.readyState = FileWriter.WRITING;
  
      var me = this;
  
      // If onwritestart callback
      if (typeof me.onwritestart === "function") {
          me.onwritestart(new ProgressEvent("writestart", {"target":me}));
      }
  
      // Write file
      exec(
          // Success callback
          function(r) {
              // If DONE (cancelled), then don't do anything
              if (me.readyState === FileWriter.DONE) {
                  return;
              }
  
              // position always increases by bytes written because file would be extended
              me.position += r;
              // The length of the file is now where we are done writing.
  
              me.length = me.position;
  
              // DONE state
              me.readyState = FileWriter.DONE;
  
              // If onwrite callback
              if (typeof me.onwrite === "function") {
                  me.onwrite(new ProgressEvent("write", {"target":me}));
              }
  
              // If onwriteend callback
              if (typeof me.onwriteend === "function") {
                  me.onwriteend(new ProgressEvent("writeend", {"target":me}));
              }
          },
          // Error callback
          function(e) {
              // If DONE (cancelled), then don't do anything
              if (me.readyState === FileWriter.DONE) {
                  return;
              }
  
              // DONE state
              me.readyState = FileWriter.DONE;
  
              // Save error
              me.error = new FileError(e);
  
              // If onerror callback
              if (typeof me.onerror === "function") {
                  me.onerror(new ProgressEvent("error", {"target":me}));
              }
  
              // If onwriteend callback
              if (typeof me.onwriteend === "function") {
                  me.onwriteend(new ProgressEvent("writeend", {"target":me}));
              }
          }, "File", "write", [this.localURL, data, this.position, isBinary]);
  };
  
  /**
   * Moves the file pointer to the location specified.
   *
   * If the offset is a negative number the position of the file
   * pointer is rewound.  If the offset is greater than the file
   * size the position is set to the end of the file.
   *
   * @param offset is the location to move the file pointer to.
   */
  FileWriter.prototype.seek = function(offset) {
      // Throw an exception if we are already writing a file
      if (this.readyState === FileWriter.WRITING) {
          throw new FileError(FileError.INVALID_STATE_ERR);
      }
  
      if (!offset && offset !== 0) {
          return;
      }
  
      // See back from end of file.
      if (offset < 0) {
          this.position = Math.max(offset + this.length, 0);
      }
      // Offset is bigger than file size so set position
      // to the end of the file.
      else if (offset > this.length) {
          this.position = this.length;
      }
      // Offset is between 0 and file size so set the position
      // to start writing.
      else {
          this.position = offset;
      }
  };
  
  /**
   * Truncates the file to the size specified.
   *
   * @param size to chop the file at.
   */
  FileWriter.prototype.truncate = function(size) {
      // Throw an exception if we are already writing a file
      if (this.readyState === FileWriter.WRITING) {
          throw new FileError(FileError.INVALID_STATE_ERR);
      }
  
      // WRITING state
      this.readyState = FileWriter.WRITING;
  
      var me = this;
  
      // If onwritestart callback
      if (typeof me.onwritestart === "function") {
          me.onwritestart(new ProgressEvent("writestart", {"target":this}));
      }
  
      // Write file
      exec(
          // Success callback
          function(r) {
              // If DONE (cancelled), then don't do anything
              if (me.readyState === FileWriter.DONE) {
                  return;
              }
  
              // DONE state
              me.readyState = FileWriter.DONE;
  
              // Update the length of the file
              me.length = r;
              me.position = Math.min(me.position, r);
  
              // If onwrite callback
              if (typeof me.onwrite === "function") {
                  me.onwrite(new ProgressEvent("write", {"target":me}));
              }
  
              // If onwriteend callback
              if (typeof me.onwriteend === "function") {
                  me.onwriteend(new ProgressEvent("writeend", {"target":me}));
              }
          },
          // Error callback
          function(e) {
              // If DONE (cancelled), then don't do anything
              if (me.readyState === FileWriter.DONE) {
                  return;
              }
  
              // DONE state
              me.readyState = FileWriter.DONE;
  
              // Save error
              me.error = new FileError(e);
  
              // If onerror callback
              if (typeof me.onerror === "function") {
                  me.onerror(new ProgressEvent("error", {"target":me}));
              }
  
              // If onwriteend callback
              if (typeof me.onwriteend === "function") {
                  me.onwriteend(new ProgressEvent("writeend", {"target":me}));
              }
          }, "File", "truncate", [this.localURL, size]);
  };
  
  module.exports = FileWriter;
  
  });
  