# Copyright 2014 NeuroData (http://neurodata.io)
# Copyright 2016 The Johns Hopkins University Applied Physics Laboratory
#
# Licensed 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.

from __future__ import print_function
from __future__ import absolute_import
from ndingest.settings.settings import Settings
settings = Settings.load()
import hashlib
import boto3
import botocore
from ndingest.util.util import Util
UtilClass = Util.load()


class CuboidBucket:

  def __init__(self, project_name, region_name=settings.REGION_NAME, endpoint_url=settings.S3_ENDPOINT):
    """Create resource for the cuboid queue"""
    
    bucket_name = CuboidBucket.getBucketName()
    self.project_name = project_name
    self.s3 = boto3.resource(
        's3', region_name=region_name, endpoint_url=endpoint_url,
        aws_access_key_id=settings.AWS_ACCESS_KEY_ID, aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY)
    try:
      self.bucket = self.s3.Bucket(bucket_name)
    except botocore.exceptions.ClientError as e:
      print (e)
      raise

  @staticmethod
  def createBucket(region_name=settings.REGION_NAME, endpoint_url=settings.S3_ENDPOINT):
    """Create the cuboid bucket"""
    
    bucket_name = CuboidBucket.getBucketName()
    s3 = boto3.resource(
        's3', region_name=region_name, endpoint_url=endpoint_url,
        aws_access_key_id=settings.AWS_ACCESS_KEY_ID, aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY)
    bucket = s3.Bucket(bucket_name)
    try:
      # creating the bucket
      response = bucket.create(
          ACL = 'private'
      )
    except Exception as e:
      print (e)
      raise

  @staticmethod
  def deleteBucket(region_name=settings.REGION_NAME, endpoint_url=settings.S3_ENDPOINT):
    """Delete the cuboid bucket"""
    
    bucket_name = CuboidBucket.getBucketName()
    s3 = boto3.resource(
        's3', region_name=region_name, endpoint_url=endpoint_url,
        aws_access_key_id=settings.AWS_ACCESS_KEY_ID, aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY)
    bucket = s3.Bucket(bucket_name)
    try:
      # deleting the bucket
      response = bucket.delete()
    except Exception as e:
      print (e)
      raise
  
  @staticmethod
  def getBucketName():
    """Generate the Bucket Name"""
    return settings.S3_CUBOID_BUCKET
  

  def putObject(self, channel_name, resolution, morton_index, time_index, cube_data, neariso=False):
    """Put object in the cuboid bucket.

    Not supported by the Boss.  Use putObjectByKey() instead.
    """
    supercuboid_key = self.generateSupercuboidKey(channel_name, resolution, morton_index, time_index, neariso=neariso)
    return self.putObjectByKey(supercuboid_key, cube_data)
    
  def putObjectByKey(self, supercuboid_key, cube_data):
    """Put object in the cuboid bucket by key"""
    
    try:
      response = self.bucket.put_object(
          ACL = 'private',
          Body = cube_data,
          Key = supercuboid_key,
          StorageClass = 'STANDARD'
      )
      return response
    except Exception as e:
      print (e)
      raise
   
  def getObjectByKey(self, supercuboid_key):
    """Get an object from the cuboid bucket based on key. """
    
    try:
      s3_obj = self.s3.Object(self.bucket.name, supercuboid_key)
      response = s3_obj.get()
      return response['Body'].read()
    except Exception as e:
      # print (e)
      raise

  def getObject(self, channel_name, resolution, morton_index, time_index, neariso=False):
    """Get object from the cuboid bucket based on parameters.

    Not supported by the Boss.  Use getObjectByKey() instead.
    """

    supercuboid_key = self.generateSupercuboidKey(channel_name, resolution, morton_index, time_index, neariso=neariso)
    return self.getObjectByKey(supercuboid_key)

  def generateSupercuboidKey(self, channel_name, resolution, morton_index, time_index, neariso=False):
    """Generate the supercuboid key"""
    return UtilClass.generateCuboidKey(self.project_name, channel_name, resolution, morton_index, time_index, neariso=neariso)

  def deleteObject(self, supercuboid_key):
    """Delete object from the upload bucket"""
    
    try:
      s3_obj = self.s3.Object(self.bucket.name, supercuboid_key)
      response = s3_obj.delete()
      return response
    except Exception as e:
      print (e)
      raise

  def getAllObjects(self):
    """Get a collection of ObjectSummary for all objects in the bucket."""

    try:
      return self.bucket.objects.all()
    except Exception as e:
      print (e)
      raise
