# 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.
# libcloud.org 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.
"""
GoGrid driver
"""
from libcloud.providers import Provider
from libcloud.types import NodeState, InvalidCredsException
from libcloud.base import Node, ConnectionUserAndKey, Response, NodeDriver
from libcloud.base import NodeSize, NodeImage, NodeLocation
import time
import hashlib

# JSON is included in the standard library starting with Python 2.6.  For 2.5
# and 2.4, there's a simplejson egg at: http://pypi.python.org/pypi/simplejson
try: import json
except: import simplejson as json

HOST = 'api.gogrid.com'
PORTS_BY_SECURITY = { True: 443, False: 80 }
API_VERSION = '1.3'

STATE = {
    "Starting": NodeState.PENDING,
    "On": NodeState.RUNNING,
    "Off": NodeState.PENDING,
    "Restarting": NodeState.REBOOTING,
    "Saving": NodeState.PENDING,
    "Restoring": NodeState.PENDING,
}

GOGRID_INSTANCE_TYPES = {'512MB': {'id': '512MB',
                       'name': '512MB',
                       'ram': 512,
                       'disk': 30,
                       'bandwidth': None,
                       'price':0.095},
        '1GB': {'id': '1GB',
                       'name': '1GB',
                       'ram': 1024,
                       'disk': 60,
                       'bandwidth': None,
                       'price':0.19},
        '2GB': {'id': '2GB',
                       'name': '2GB',
                       'ram': 2048,
                       'disk': 120,
                       'bandwidth': None,
                       'price':0.38},
        '4GB': {'id': '4GB',
                       'name': '4GB',
                       'ram': 4096,
                       'disk': 240,
                       'bandwidth': None,
                       'price':0.76},
        '8GB': {'id': '8GB',
                       'name': '8GB',
                       'ram': 8192,
                       'disk': 480,
                       'bandwidth': None,
                       'price':1.52}}


class GoGridResponse(Response):
    def success(self):
        if self.status == 403:
          raise InvalidCredsException()
        if not self.body:
            return None
        return json.loads(self.body)['status'] == 'success'

    def parse_body(self):
        if not self.body:
            return None
        return json.loads(self.body)

    def parse_error(self):
        if not self.object:
            return None
        return self.object['message']

class GoGridConnection(ConnectionUserAndKey):

    host = HOST
    responseCls = GoGridResponse

    def add_default_params(self, params):
        params["api_key"] = self.user_id
        params["v"] = API_VERSION
        params["format"] = 'json'
        params["sig"] = self.get_signature(self.user_id, self.key)

        return params
        
    def get_signature(self, key, secret):
        """ create sig from md5 of key + secret + time """
        m = hashlib.md5(key+secret+str(int(time.time())))
        return m.hexdigest()

class GoGridNode(Node):
    # Generating uuid based on public ip to get around missing id on
    # create_node in gogrid api
    #
    # Used public ip since it is not mutable and specified at create time,
    # so uuid of node should not change after add is completed
    def get_uuid(self):
        return hashlib.sha1(
            "%s:%d" % (self.public_ip,self.driver.type)
        ).hexdigest()

class GoGridNodeDriver(NodeDriver):

    connectionCls = GoGridConnection
    type = Provider.GOGRID
    name = 'GoGrid API'

    _instance_types = GOGRID_INSTANCE_TYPES

    def get_state(self, element):
        try:
            return STATE[element['state']['name']]
        except:
            pass
        return NodeState.UNKNOWN

    def get_ip(self, element):
        return element['ip']['ip']

    def get_id(self,element):
        return element['id']

    def _to_node(self, element):
        state = self.get_state(element)
        ip = self.get_ip(element)
        id = self.get_id(element)
        n = GoGridNode(id=id,
                 name=element['name'],
                 state=state,
                 public_ip=[ip],
                 private_ip=[],
                 driver=self.connection.driver)
        return n

    def _to_image(self, element):
        n = NodeImage(id=element['id'],
                      name=element['friendlyName'],
                      driver=self.connection.driver)
        return n

    def _to_images(self, object):
        return [ self._to_image(el)
                 for el in object['list'] ]

    def list_images(self, location=None):
        images = self._to_images(
                    self.connection.request('/api/grid/image/list').object)
        return images

    def get_uuid(self, field):
        uuid_str = "%s:%s" % (field,self.connection.user_id)
        return hashlib.sha1(uuid_str).hexdigest()

    def list_nodes(self):
        res = self.server_list()
        return [ self._to_node(el)
                 for el
                 in res['list'] ]

    def reboot_node(self, node):
        id = node.id
        power = 'restart'
        res = self.server_power(id, power)
        if not res.success():
            raise Exception(res.parse_error())
        return True

    def destroy_node(self, node):
        id = node.id
        res = self.server_delete(id)
        if not res.success():
            raise Exception(res.parse_error())
        return True

    def server_list(self):
        return self.connection.request('/api/grid/server/list').object

    def server_power(self, id, power):
        # power in ['start', 'stop', 'restart']
        params = {'id': id, 'power': power}
        return self.connection.request("/api/grid/server/power", params)

    def server_delete(self, id):
        params = {'id': id}
        return self.connection.request("/api/grid/server/delete", params)

    def get_first_ip(self):
        params = {'ip.state': 'Unassigned', 'ip.type':'public'}
        object = self.connection.request("/api/grid/ip/list", params).object
        return object['list'][0]['ip']

    def list_sizes(self, location=None):
        return [ NodeSize(driver=self.connection.driver, **i) 
                    for i in self._instance_types.values() ]

    def list_locations(self):
        return [NodeLocation(0, "GoGrid Los Angeles", 'US', self)]

    def create_node(self, **kwargs):
        name = kwargs['name']
        image = kwargs['image']
        size = kwargs['size']
        first_ip = self.get_first_ip()
        params = {'name': name,
                  'image': image.id,
                  'description': kwargs.get('description',''),
                  'server.ram': size.id,
                  'ip':first_ip}

        object = self.connection.request('/api/grid/server/add',
                                         params=params).object
        node = self._to_node(object['list'][0])

        return node
