"use strict";

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
}

var azure = require("azure-storage");
var crc32 = require("fast-crc32c");
var path = require("path");
var fs = require("fs");

function getAZURE(options) {
  var blobService = azure.createBlobService(
    options.accountName,
    options.accountKey
  );
  return new AzureWrapper(blobService);
}

var AzureWrapper = function AzureWrapper(blobService) {
  _classCallCheck(this, AzureWrapper);

  this.blobService = blobService;
  var self = this;

  self.createBucket = function(name) {
    if (!name) {
      return new Promise(function(resolve, reject) {
        reject({
          status: 400,
          message: "Invalid parameters"
        });
      });
    }

    return new Promise(function(resolve, reject) {
      self.blobService.createContainerIfNotExists(
        name,
        {
          publicAccessLevel: "blob"
        },
        function(err, data) {
          if (!err) {
            resolve({
              status: 201,
              message: 'Bucket "' + name + '" was created successfully'
            });
          } else {
            reject({
              status: 400,
              message: err.message
            });
          }
        }
      );
    });
  };

  self.deleteBucket = function(name) {
    if (!name) {
      return new Promise(function(resolve, reject) {
        reject({
          status: 400,
          message: "Invalid parameters"
        });
      });
    }

    return new Promise(function(resolve, reject) {
      self.blobService.deleteContainerIfExists(name, function(err, data) {
        if (!err) {
          resolve({
            status: 200,
            message: 'Bucket "' + name + '" was deleted successfully'
          });
        } else {
          reject({
            status: 400,
            message: err.message
          });
        }
      });
    });
  };

  self.uploadFile = function(bucketName, filePath) {
    if (!bucketName || !filePath) {
      return new Promise(function(resolve, reject) {
        reject({
          status: 400,
          message: "Invalid parameters"
        });
      });
    }

    var remoteFilename = path.basename(filePath);
    return new Promise(function(resolve, reject) {
      self.blobService.createBlockBlobFromLocalFile(
        bucketName,
        remoteFilename,
        filePath,
        function(err, result, response) {
          if (!err) {
            resolve({
              status: 200,
              message:
                'File "' +
                filePath +
                '" was uploaded successfully to bucket "' +
                bucketName +
                '"'
            });
          } else {
            reject({
              status: 400,
              message: err.message
            });
          }
        }
      );
    });
  };

  self.downloadFile = function(bucketName, filename, saveToPath) {
    if (!bucketName || !filename || !saveToPath) {
      return new Promise(function(resolve, reject) {
        reject({
          status: 400,
          message: "Invalid parameters"
        });
      });
    }
    var params = {
      Bucket: bucketName,
      Key: filename
    };
    var file = fs.createWriteStream(saveToPath);

    return new Promise(function(resolve, reject) {
      self.blobService.getBlobToStream(bucketName, filename, file, function(
        err,
        result,
        response
      ) {
        if (!err) {
          resolve({
            status: 200,
            message:
              'File "' +
              filename +
              '" was downloaded successfully from bucket "' +
              bucketName +
              '"'
          });
        } else {
          reject({
            status: 400,
            message: err.message
          });
        }
      });
    });
  };

  self.createFileFromText = function(bucketName, filename, object) {
    var shouldSimulateFileCorruption =
      arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;

    if (!bucketName || !filename || !object) {
      return new Promise(function(resolve, reject) {
        reject({
          status: 400,
          message: "Invalid parameters"
        });
      });
    }

    return new Promise(function(resolve, reject) {
      var stringifiedObject = JSON.stringify(object);
      self.blobService.createBlockBlobFromText(
        bucketName,
        filename,
        stringifiedObject,
        function(err, data) {
          if (!err) {
            // Check whether file was properly uploaded
            var localFileCrc32 = crc32.calculate(stringifiedObject);
            self.readFile(bucketName, filename).then(function(response) {
              var remoteFileCrc32 = void 0;
              var data = JSON.stringify(response.data);
              if (shouldSimulateFileCorruption) {
                data += "corrupted-sufix";
              }
              remoteFileCrc32 = crc32.calculate(data);

              if (localFileCrc32 === remoteFileCrc32) {
                resolve({
                  status: 200,
                  message:
                    'Object "' +
                    filename +
                    '" was saved successfully in bucket "' +
                    bucketName +
                    '"'
                });
              } else {
                reject({
                  status: 400,
                  message:
                    'CRC32 validation error. Object "' +
                    filename +
                    '" could not be uploaded successfully'
                });
              }
            });
          } else {
            reject({
              status: 400,
              message: err.message
            });
          }
        }
      );
    });
  };

  self.getListOfFiles = function(bucketName) {
    if (!bucketName) {
      return new Promise(function(resolve, reject) {
        reject({
          status: 400,
          message: "Invalid parameters"
        });
      });
    }

    return new Promise(function(resolve, reject) {
      self.blobService.listBlobsSegmented(bucketName, null, function(
        err,
        data
      ) {
        if (!err) {
          var objects = [];
          data.entries.forEach(function(element) {
            objects.push({
              filename: element.name
            });
          });
          resolve({
            status: 200,
            data: objects,
            message:
              'The list of objects was fetched successfully from bucket "' +
              bucketName +
              '"'
          });
        } else {
          reject({
            status: 400,
            message: err.message
          });
        }
      });
    });
  };

  self.deleteFile = function(bucketName, filename) {
    if (!bucketName || !filename) {
      return new Promise(function(resolve, reject) {
        reject({
          status: 400,
          message: "Invalid parameters"
        });
      });
    }

    return new Promise(function(resolve, reject) {
      self.blobService.deleteBlob(bucketName, filename, function(err, data) {
        if (!err) {
          resolve({
            status: 200,
            message:
              'Object "' +
              filename +
              '" was deleted successfully from bucket "' +
              bucketName +
              '"'
          });
        } else {
          reject({
            status: 400,
            message: err.message
          });
        }
      });
    });
  };

  self.readFile = function(bucketName, filename) {
    if (!bucketName || !filename) {
      return new Promise(function(resolve, reject) {
        reject({
          status: 400,
          message: "Invalid parameters"
        });
      });
    }

    return new Promise(function(resolve, reject) {
      self.blobService.getBlobToText(bucketName, filename, function(err, data) {
        if (!err) {
          resolve({
            status: 200,
            data: JSON.parse(data),
            message:
              'Object "' +
              filename +
              '" was fetched successfully from bucket "' +
              bucketName +
              '"'
          });
        } else {
          reject({
            status: 400,
            message: err.message
          });
        }
      });
    });
  };
};

module.exports = {
  getAZURE: getAZURE
};
