import json
import logging
import urlparse

import requests
from multicorn import ForeignDataWrapper
from multicorn.utils import log_to_postgres

OPERATORS = {
    '=': 'exact',
    '<': 'lt',
    '>': 'gt',
    '<=': 'le',
    '>=': 'ge',
    '<>': 'ne',
    '~~': 'exact',
    '~~*': 'iexact',
    '!~~*': 'notiexact',
    '!~~': 'notexact',
    ('=', True): 'in',
    ('<>', False): 'notin'
}


class FalconApiFDW(ForeignDataWrapper):
    def __init__(self, options, columns):
        super(FalconApiFDW, self).__init__(options, columns)
        self.columns = columns
        self.options = options
        self._rowid_column = columns.keys()[0]
        self.params = {}
        if 'params' in self.options:
            self.params = urlparse.parse_qs(self.options['params'])
        if 'url' not in self.options:
            log_to_postgres('Falcon API FDW: url option is required',
                            level=logging.ERROR,
                            hint='Try adding the missing option in the table '
                                 'creation statement')

    def get_params(self, quals):
        params = {}
        for qual in quals:
            op = OPERATORS.get(qual.operator, None)
            if op is None:
                # skip unknown ops as PostgreSQL will apply them anyway
                continue
            params['{}__{}'.format(qual.field_name, op)] = qual.value
        return params

    def execute(self, quals, columns):
        params = self.params.copy()
        params.update(self.get_params(quals))
        response = requests.get(self.options['url'],
                                params=params)
        log_to_postgres('Request: {} {} {}'.format(response.request.method,
                                                   response.request.url,
                                                   response.request.body),
                        level=logging.DEBUG)
        log_to_postgres('Response: ' + response.text,
                        level=logging.DEBUG)
        results = []
        for result in response.json()['results']:
            for attribute, value in result.iteritems():
                if isinstance(value, (dict, list)):
                    result[attribute] = json.dumps(value)
            results.append(result)
        return results

    @property
    def rowid_column(self):
        return self._rowid_column

    def insert(self, new_values):
        response = requests.post(self.options['url'],
                                 params=self.params,
                                 json=new_values)
        return response.json()

    def update(self, old_values, new_values):
        pk = new_values.pop('id')
        response = requests.put('{}/{}'.format(self.options['url'], pk),
                                params=self.params,
                                json=new_values)
        return response.json()

    def delete(self, old_values):
        pk = old_values.pop('id')
        response = requests.delete('{}/{}'.format(self.options['url'], pk),
                                   params=self.params)
        return response.json()

@@ -1426,220 +1426,37 @@
 def 
-execute(self, quals, columns):%0A        params = self.params.copy()%0A        params.update(self.get_params(quals))%0A        response = requests.get(self.options%5B'url'%5D,%0A                                params=params)
+log_response(self, response):
 %0A   
@@ -1811,32 +1811,290 @@
 l=logging.DEBUG)
+%0A%0A    def execute(self, quals, columns):%0A        params = self.params.copy()%0A        params.update(self.get_params(quals))%0A        response = requests.get(self.options%5B'url'%5D,%0A                                params=params)%0A        self.log_response(response)
 %0A        results
@@ -2477,32 +2477,154 @@
 f, new_values):%0A
+        data = %7Bkey: value%0A                for key, value in new_values.iteritems()%0A                if value is not None%7D%0A
         response
@@ -2748,34 +2748,64 @@
        json=
-new_values
+data)%0A        self.log_response(response
 )%0A        re
@@ -2847,26 +2847,21 @@
 e(self, 
-old_values
+rowid
 , new_va
@@ -2871,42 +2871,8 @@
 s):%0A
-        pk = new_values.pop('id')%0A
     
@@ -2927,34 +2927,37 @@
 options%5B'url'%5D, 
-pk
+rowid
 ),%0A             
@@ -3044,16 +3044,52 @@
 values)%0A
+        self.log_response(response)%0A
         
@@ -3137,54 +3137,15 @@
 lf, 
-old_values):%0A        pk = old_values.pop('id')
+rowid):
 %0A   
@@ -3216,10 +3216,13 @@
 '%5D, 
-pk
+rowid
 ),%0A 
@@ -3267,32 +3267,68 @@
 ms=self.params)%0A
+        self.log_response(response)%0A
         return r

fix insert, update and delete