import psycopg2
import fnmatch
import os, os.path
import glob
import subprocess
import shutil
import datetime
import time
try:
    import ogr
except:
    pass

# load configuration
try:
    from .config import l2 as l2config
except:
    pass

class ConnectionError(Exception):
    '''Base class for exceptions in this module.'''
    pass

class SimpleDatabase:
    ''' Methods common for all tables'''

    def initialize(self):
        '''Connect to the database

            Set values of host, user, ...

            Parameters:
            -----------
                dbSchema: dictionary
                    Values of host, user, ...

            Modifies:
                Set values of host, user, ...
                Opens connection to the database
        '''
        #create table with fields from schema (to be set prior to caling __init__)
        self.create_table()

    def connect_postgresql(self, t=15, w=15):
        '''Use self.hots, self.user, etc for connecting to PostgreSQL database '''
        # set SHOW TABLES
        self.showTables = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';"
        conn = None
        # try to connect several times with timeout
        for i in range(t):
            try:
                conn = psycopg2.connect(host='postgis',
                                        database='test',
                                        user='opengeo',
                                        password='open2012geo')
            except:
                print 'Cannot connect to database in try %d' % i
                time.sleep(w)
            else:
                break

        if conn is None:
            raise ConnectionError

        return conn

    def connect_mysql(self):
        '''Use self.hots, self.user, etc for connecting to MySQL database '''
        # set SHOW TABLES
        self.showTables = "SHOW TABLES"

        # return connection
        return MySQLdb.connect(host='mysql',
                                db='satMetadata',
                                user='sat',
                                passwd='123sat')

    def exist_table(self, table):
        ''' Check if table already exists'''
        # connect to the database
        cur = self.connect_postgresql().cursor()
        # get list of tables in the database
        cur.execute(self.showTables)
        rows = cur.fetchall()
        cur.connection.commit()
        tables = [str(r[0]) for r in rows]
        cur = None
        return table in tables

    def create_table(self):
        ''' Create a table based on the layout in self.fields

            Modifies:
            ---------
                Creates a table in the dataase. Field names and types are taken
                from self.fields dictionary
        '''
        # connect to the database
        cur = self.connect_postgresql().cursor()

        #if table not exist, create
        if self.exist_table(self.table):
            print '%s exist!' % self.table
        else:
            print 'Creating %s : ' % self.table
            queryString = 'CREATE TABLE %s (' % self.table
            #field by default:
            queryString += 'id SERIAL PRIMARY KEY, '

            # loop through all fileds
            for field in self.fields:
                queryString += '%s %s, ' % (field, self.fields[field])
            queryString += ')'
            queryString = queryString.replace(', )', ')')+ ';'
            # execute query and create table
            cur.execute(queryString)
            cur.connection.commit()

        # disconnect
        cur = None

    def exist_entry(self, cur, fieldValue=None, fieldName='name', tableName=None):
        ''' Check if entry is already in table and return content

            Generate SQL query which checks if the record exist. If so the query
            returns this record. The value is then returned by the function.

            Parameters:
            -----------
                fieldValue: string [None]
                    Value of the field to compar with
                fieldName: string ['name']
                    Name of the field to search matchups
                tableName: string [None]
                    Name of the table to search mathes for. [self.table] if None

            Returns:
            --------
                exist: boolean
                    True/False if entry exits/not
                row: list
                    All values from the matching row
        '''
        #set default tableName
        if tableName is None:
            tableName  = self.table

        #select rows where <fieldName>=<fieldValue> and count
        queryString = 'SELECT * FROM %s WHERE %s = %s ' % (tableName, fieldName, fieldValue)
        cur.execute(queryString)
        row = cur.fetchone()
        cur.connection.commit()
        return row is not None, row

    def get_entry_id(self, cur, entryName):
        '''Find or add entry in the table and return its ID'''
        rowExist, rowValue = self.exist_entry(cur, entryName)
        if rowExist:
            entryID = rowValue[0]
        else:
            queryString = 'INSERT INTO %s (name) values (%s)' % (self.table, entryName)
            print queryString
            cur.execute(queryString)
            cur.connection.commit()
            entryID = self.exist_entry(cur, entryName)[1][0]

        return entryID

    def get_list(self, tableName=None, fieldName=None, value=None):
        ''' Get list of records satisfying criteria'''

        #set default tableName
        if tableName is None:
            tableName = self.table

        queryString = " SELECT * FROM %s AS tb1 " % tableName
        if fieldName is not None and value is not None:
            queryString += " WHERE TRIM(BOTH FROM tb1.%s) LIKE '%s'" % (fieldName, value)
        print '\n\nqueryString:\n', queryString
        cur = self.connect_postgresql().cursor()
        cur.execute(queryString)
        rows = cur.fetchall()
        cur.connection.commit()
        fields = [f[0] for f in cur.description]
        cur.connection.commit()
        cur = None
        return rows, fields

class PathsCatalog(SimpleDatabase):
    ''' Create database of paths of input files'''

    def __init__(self):
        '''Create table with paths'''

        #set table name and fields
        self.table = 'cat_paths'
        self.fields = {'name': 'CHAR (250)'}

        #connect to database, create table
        self.initialize()


class SensorsCatalog(SimpleDatabase):
    '''Create catalog of sensors of input files'''

    def __init__(self):
        '''Create table with sensors'''

        #set table name and fields
        self.table = 'cat_sensors'
        self.fields = {'name': 'CHAR (250)'}

        #connect to database, create table
        self.initialize()


class ImagesCatalog(SimpleDatabase):
    ''' Methods common for all tables with satellite images'''
    # name of the table
    table = ''
    # list of fields
    fields = []

    def __init__(self, pc=None, sc=None):
        '''Create Catalog:
            * Open/Create table
            * Create view
        '''
        # open paths and sensors catalog, connect, create table
        self.create_catalog(pc, sc)

        # create view which joins cat_images, cat_paths, cat_sensors and current table
        self.create_view()

    def create_catalog(self, pc=None, sc=None):
        '''Create paths catalog, sensors catalog and catalog with images'''

        #choose or create PathsCatalog
        self.pc = pc
        if self.pc is None:
            self.pc = PathsCatalog()

        #choose or create SensorsCatalog
        self.sc = sc
        if self.sc is None:
            self.sc = SensorsCatalog()

        #connect to database, create table
        self.initialize()

    def insert_entry(self, cur, img):
        ''' Insert full record in the table. Values are taken from img metadata

        Parameters:
        -----------
            img: Nansat, Nansat2, MerisImage, ...
                Input image that has metadata

        Modifies:
        ---------
            Inserts a record with all values to a table
        '''
        imgMetadata = img.get_metadata()

        #generate query string with filed names from schema and with data friom ImageObject
        fieldNames = ''
        fieldValues = ''
        for field in self.fields:
            fieldValue = imgMetadata.get(field, False)
            if fieldValue:
                fieldNames += '%s, ' % field
                fieldValues += '%s, ' % fieldValue
        queryString = 'INSERT INTO %s (%s) values (%s)' %(self.table, fieldNames, fieldValues)
        queryString = queryString.replace(', )', ')')
        # execute the SQL query - insert record
        print queryString
        cur.execute(queryString)
        cur.connection.commit()

    def export_view(self, textFileName, tableName=None):
        '''Export view into text file'''
        #set default viewName
        if tableName is None:
            tableName = self.table + '_view'

        # get names of fields from the view
        queryString = 'SELECT * FROM %s' % tableName
        self.cur.execute(queryString)
        fields = [f[0] for f in self.cur.description]
        self.cur.connection.commit()

        # generate query te get border AsText
        queryString = 'SELECT '
        for field in fields:
            if field == 'border':
                fieldName = 'AsText(border),'
            else:
                fieldName = field + ','
            queryString += fieldName

        #less last comma
        queryString = queryString[:-1]
        queryString += ' FROM %s' % tableName

        # get all rows
        self.cur.execute(queryString)
        rows = self.cur.fetchall()
        self.cur.connection.commit()

        # open file
        oFile = file(textFileName, 'wt')
        # write header
        for field in fields:
            oFile.write(field+'; ')
        oFile.write('\n')
        # write rows
        for row in rows:
            for item in row:
                oFile.write(str(item)+'; ')
            oFile.write('\n')
        oFile.close()

    def import_view(self, textFileName):
        '''Import data from text file'''
        # open file and read contents
        iFile = file(textFileName, 'rt')
        iFileLines = iFile.readlines()
        # get names of fields
        fieldNames = [fn.strip() for fn in iFileLines[0].split(';')]
        # for each row
        for row in iFileLines[1:]:
            # get values of fields
            fieldValues = [r.strip() for r in row.split(';')]
            # create FakeImag
            img = FakeImage(fieldNames, fieldValues)
            # add fake image
            self.add_image(img)

    def get_sensor_list(self, sensor):
        ''' Get full list of all records for given sensor'''

        return self.get_list(self.viewName, 'sensor', sensor)

"""
    def delete_image(self, entryId):
        '''Remove image from database and delete files'''
        #get entry content from from row number
        existEntry, entryCont = self.exist_entry(entryId, 'id')

        #if such entry exists
        if not existEntry:
            print 'Entry %d does not exist!' % entryId
        else:
            #get image file name
            fileName = entryCont[1]
            print fileName

            #delete entry from the database
            query = 'DELETE from %s WHERE name="%s"' % (self.dbCatalogName, fileName)
            print query
            self.db.cursor().execute(query)
            #delete files
            mapPath = '%s%s%s' % (self.mapDir, fileName, self.mapExt)
            previewPath = '%s%s%s' % (self.previewDir, fileName, self.previewExt)
            print 'DELETE:\n ==> %s\n ==> %s\n ==> %s\n' % (mapPath, previewPath)
            try:
                os.remove(mapPath)
            except:
                print '%s file cannot be deleted' % (mapPath)
            try:
                os.remove(previewPath)
            except:
                print '%s file cannot be deleted' % (previewPath)


    def clean_database(self):
        '''Delete all images marked as 'TOBEDELETED' '''
        cursor = self.db.cursor()
        cursor.execute('SELECT * from %s where deleteit>0' % self.table)
        rows = cursor.fetchall()
        for row in rows:
            print 'Delete: %d ' % row[0]
            self.delete_image(row[0])
"""

class CommonImagesCatalog(ImagesCatalog):
    '''Table with common info on all satellite images'''

    def __init__(self, pc=None, sc=None):
        '''Create table with common info about all images'''
        #set table name and fields
        self.table = 'cat_images'
        self.fields = {'name':      'CHAR (250)',
                      'sensstart': 'TIMESTAMP',
                      'border':    'GEOMETRY',
                      'path_id':    'INT',
                      'sensor_id':  'INT'}

        # create Catalog
        ImagesCatalog.__init__(self, pc, sc)

    def add_image(self, img):
        '''Add records to cat_sensors, cat_paths, cat_images'''
        cur = self.connect_postgresql().cursor() # connect
        imgMetadata = img.get_metadata()
        #get id of the sensor from cat_sensors and insert into image object
        sensorID = self.sc.get_entry_id(cur, imgMetadata['sensor'])
        print 'Sensor ID: ', sensorID
        img.set_metadata('sensor_id', str(sensorID))

        #get id of the path from cat_paths and insert into image object
        pathID = self.pc.get_entry_id(cur, imgMetadata['path'])
        print 'PATH ID: ', pathID
        img.set_metadata('path_id', str(pathID))

        #Insert entry into main table (name, date, etc)
        if not self.exist_entry(cur, imgMetadata['name'])[0]:
            self.insert_entry(cur, img)
        cur = None

    def create_view(self):
        '''Create view from given fields'''
        self.viewName = '%s_view' % self.table

        if self.exist_table(self.viewName):
            print 'View %s already exsits' % self.viewName
        else:
            viewQuery = '''
                CREATE OR REPLACE VIEW %s AS
                SELECT ci.name, cp.name AS path, cs.name as sensor, ci.sensstart, ci.border
                FROM cat_images AS ci
                JOIN cat_sensors as cs ON ci.sensor_id = cs.id
                JOIN cat_paths as cp ON ci.path_id = cp.id
            ''' % self.viewName
            print viewQuery
            cur = self.connect_postgresql().cursor()
            cur.execute(viewQuery)
            cur.connection.commit()
            cur = None

    def fill_database(self, sensor, inputDir, fileMask, ImageClass):
        ''' Add all images from the given directory'''
        # get list of available files
        inputFiles = glob.glob(inputDir + fileMask)
        inputFiles = [os.path.basename(i) for i in inputFiles]
        #print inputFiles
        # get list of files in db
        dbFiles = self.get_sensor_list(sensor)[0]
        dbFiles = [row[0].strip() for row in dbFiles]
        #print dbFiles

        # add new files to db
        for inputFile in inputFiles:
            filePathName = os.path.join(inputDir, inputFile)
            if ((inputFile not in dbFiles) and not os.path.exists(filePathName + '.bad')):
                print 'Proc : ', inputFile
                try:
                    #read image using Catalog specific reader (Nansat child)
                    img = ImageClass(filePathName, logLevel=10)
                except:
                    print 'Unable to open image %s' % inputFile
                    try:
                        # make an empty copy of the file to file.bad
                        print 'Creating %s' % filePathName+'.bad'
                        open(filePathName+'.bad', 'w').close()
                    except:
                        print 'Unable to make BAD copy of %s' % inputFile
                else:
                    # add image to database
                    print '%s was opened. Adding...' % inputFile
                    self.add_image(img)

                img = None # destroy the image

    def fill_database_shp(self, sensor, inputSHP):
        ''' Add all images from the given directory'''

        # get layer from dataset
        ds = ogr.Open(inputSHP)
        dsLayer = ds.GetLayer(0)

        #print inputFiles
        # get list of files in db
        dbFiles = self.get_sensor_list(sensor)[0]
        dbFiles = [row[0].strip() for row in dbFiles]
        #print dbFiles

        # add new files to db
        for feat in dsLayer:
            scene_id = str(feat.GetFieldAsString('scene_id'))
            if scene_id not in dbFiles:
                print 'Proc : ', scene_id
                try:
                    acq_date = str(feat.GetFieldAsString('acq_date'))
                    sensstart = datetime.datetime(int(acq_date[:4]), int(acq_date[4:6]), int(acq_date[6:])).strftime('%Y-%m-%d %H:%M:%S.%f')
                    imgMetadata = {
                        'name': str(feat.GetFieldAsString('scene_id')),
                        'path': '',
                        'sensstart': sensstart,
                        'Orbit': feat.GetFieldAsString('Orbit'),
                        'ql_link': feat.GetFieldAsString('ql_link'),
                        'border': feat.GetGeometryRef().ExportToWkt(),
                        'sensor': sensor,
                    }

                    img = FakeImage(fieldDict = imgMetadata)
                    print img.get_metadata()
                    self.add_image(img)
                except:
                    print 'cannot insert ', scene_id

    def find_image(self, name='%', sensor='%', start=None, stop=None, polygon=None, **kwargs):
        '''Find image which satisfies input criteria'''

        queryString = ('''SELECT name, path, sensor, sensstart, AsText(border) FROM %s WHERE
                         name LIKE '$%s$' AND
                         sensor LIKE '$%s$'
                         ''' % (
                        self.viewName,
                        name,
                        sensor))
        if start is not None:
            queryString += " AND sensstart >= '%s 00:00:00' " % start
        if stop is not None:
            queryString += " AND sensstart <= '%s 23:59:59' " % stop
        if polygon is not None:
            queryString += "AND Intersects(border, %s)" % polygon

        queryString = queryString.replace('$', '%')
        print queryString

        self.cur.execute(queryString)
        rows = self.cur.fetchall()
        self.cur.connection.commit()
        return rows

class MerisCatalog(ImagesCatalog):
    '''Catalog of MERIS images'''

    def estimate_intersect(self, level=1):
        ''' Estimate for each image coverage by other images (from other stations'''
        # constants
        stationLetters = ['K', 'A', 'E']
        tmpTableName = 'cat_tmp_meris'

        # try to delete the tmp table
        query = '''
        DROP TABLE %s
        ''' % tmpTableName
        #print query
        try:
            self.cur.execute(query)
            self.cur.connection.commit()
        except:
            print 'Table %s does not exist' % tmpTableName

        # make table with all MERIS images (SQL)
        query = '''
        CREATE TABLE %s AS (
        SELECT ci.id, ci.name, ci.sensstart, cm.sensend, cm.orbit, MID(ci.name, 14, 1) AS station, MID(ci.name, 5, 3) AS resolution, MID(ci.name, 9, 1) AS level
        FROM cat_images AS ci
        JOIN cat_sensors as cs ON ci.sensor_id = cs.id
        JOIN cat_meris as cm ON cm.image_id = ci.id
        WHERE cs.name LIKE 'meris'
        )
        ''' % tmpTableName
        #print query
        self.cur.execute(query)
        query = 'ALTER TABLE %s ADD PRIMARY KEY(id)' % tmpTableName
        #print query
        self.cur.execute(query)
        self.cur.connection.commit()

        # query for selecting brothers (other images with same orbit)
        broQuery = '''
        SELECT * FROM %s AS tmp
        WHERE tmp.station='%s'
        AND tmp.resolution='FRS'
        AND tmp.level='%d'
        AND tmp.orbit=%d
        '''

        # get list of required images
        for currentStation in stationLetters:
            query = '''
            SELECT * FROM %s AS tmp
            WHERE tmp.station='%s'
            AND tmp.resolution='FRS'
            AND tmp.level='%d'
            ''' % (tmpTableName, currentStation, level)
            #print query
            self.cur.execute(query)
            rows = self.cur.fetchall()
            self.cur.connection.commit()

            for row in rows:
                #print row
                # get image time, convert to number, make interval
                d1 = row[2]
                d2 = row[3]
                dN1 = d1.toordinal()+(d1 - d1.fromordinal(d1.toordinal())).total_seconds()/24/60/60
                dN2 = d2.toordinal()+(d2 - d2.fromordinal(d2.toordinal())).total_seconds()/24/60/60
                dI = interval[dN1, dN2]
                dILength = (dI[0][1] - dI[0][0])
                #print d1N, d2N, dI
                # get brothers
                #print query % (tmpTableName, broStation, row[4])
                allBroI = interval()
                for broStation in stationLetters:
                    if not broStation==currentStation:
                        self.cur.execute(broQuery % (tmpTableName, broStation, level, row[4]))
                        broRows = self.cur.fetchall()
                        for broRow in broRows:
                            #print '    ', broRow
                            # get image time, convert to number
                            d1 = broRow[2]
                            d2 = broRow[3]
                            broN1 = d1.toordinal()+(d1 - d1.fromordinal(d1.toordinal())).total_seconds()/24/60/60
                            broN2 = d2.toordinal()+(d2 - d2.fromordinal(d2.toordinal())).total_seconds()/24/60/60
                            # union with all brothers interval
                            allBroI = allBroI | interval[broN1, broN2]
                            #print '    ', broN1, broN2, allBroI

                # intersect the current interval with unioned interval
                dInt = dI & allBroI
                #print dI, allBroI, dInt

                # find length of the intersection
                dIntLength = 0
                for i in dInt.components:
                    dIntLength += i[0][1] - i[0][0]

                # find % of intersection
                dIPercent = dIntLength / dILength

                print row[1], dILength, dIPercent

    def find_bad_images(self):
        ''' Find MERIS images that are contained within other images'''
        queries = []
        queries.append('''
            DROP INDEX mercat_name_ind ON meris_catalog
        ''')
        queries.append('''
            CREATE INDEX mercat_name_ind ON meris_catalog (orbit, zone)
        ''')
        # FIND BAD IMAGES: within or equal to other existing images
        queries.append('''
            UPDATE meris_catalog m1
            JOIN meris_catalog m2 ON m1.orbit=m2.orbit AND m1.zone=m2.zone AND m1.resolution=m2.resolution AND m1.level=m2.level
            SET m1.deleteit = 1
            WHERE m1.id > m2.id AND m1.sensstart >= m2.sensstart-1 AND m1.sensend <= m2.sensend+1
        ''')
        #perfrom queries
        for query in queries:
            try:
                self.cur.execute(query)
                self.cur.connection.commit()
            except:
                print "BAD SQL: ", query


class L2Catalog(ImagesCatalog):
    ''' Satellite Images with L2-processing (visualization, or more advanced) '''

    def __init__(self, catalogName):
        '''Open l2-catalog'''
        # Get configuration from config file
        self.conf = l2config[catalogName]

        # set table name, fields
        self.table = str(self.conf['table'])
        self.fields = {}
        for fieldName in self.conf['fields'].keys():
            self.fields[fieldName] = str(self.conf['fields'][fieldName])

        # set default name of the sensor
        self.sensor = str(self.conf['sensor'])

        # create/open catalog
        ImagesCatalog.__init__(self)

        #choose or create CommonImagesCatalog
        self.cic = CommonImagesCatalog()

    def process(self, ImageClass):
        '''L2 processing of image'''
        # get criteria of processing from config file
        sensor = self.conf['sensor']
        firstDate = self.conf['firstDate']
        lastDate = self.conf['lastDate']
        region = self.conf['region']
        minInter = self.conf['minInter']
        mask = self.conf['mask']

        print 'firstDate, lastDate, region', firstDate, lastDate, region

        # get list of images for processing
        rows, fields = self.get_new_images(self.sensor, firstDate, lastDate, region, minInter, mask)
        nameField = fields.index('name')
        pathField = fields.index('path')
        #print rows

        # process images and add to L2-catalog
        cur = self.connect_postgresql().cursor()
        for row in rows:
            # get full path to the image
            filePathName = os.path.join(row[pathField].strip(), row[nameField].strip())
            print filePathName,
            if not os.path.exists(filePathName):
                print ' does not exist!'
                continue
            # open image using Nansat child
            print ' opening...'
            img = ImageClass(filePathName, logLevel=10)

            # l2-process the image
            l2_processor = eval('img.%s' % self.conf['opts']['name'])
            status = l2_processor(self.conf['opts'])
            print 'l2-status: ', status
            # add to database if processing was successfull
            if status == 0:
                #get id of the image in the cat_images
                imageID = self.cic.get_entry_id(cur, img.get_metadata('name'))
                img.set_metadata('image_id', str(imageID))
                self.insert_entry(cur, img)
            img = None
        cur = None

    def get_new_images(self, sensor, firstDate='', lastDate='', region='', minInter=0, mask='%'):
        '''Get list of images for processing from database using SQL query'''

        # replace temporary table with valid geometries only
        cur = self.connect_postgresql().cursor()
        cur.execute('DROP TABLE IF EXISTS cat_images_view_tmp')
        cur.connection.commit()
        queryString = '''
            SELECT *
            INTO TEMP cat_images_view_tmp
            FROM cat_images_view
        '''
        if region != '':
            queryString += '''
            WHERE st_isvalid(border) = true;
        '''
        cur.execute(queryString)
        cur.connection.commit()

        queryString = '''
            SELECT ic.*, l2.name
            FROM cat_images_view_tmp AS ic
            LEFT JOIN %s AS l2
            ON ic.name = l2.name
            WHERE ic.sensor='%s' AND l2.name IS NULL ''' % (self.viewName, sensor)
        if mask != '':
            queryString += " AND ic.name LIKE '%s' " % mask
        if firstDate != '':
            queryString += " AND ic.sensstart >= '%s' " % firstDate
        if lastDate != '':
            queryString += " AND ic.sensstart <= '%s' " % lastDate
        if region != '':
            polygonString = "GeometryFromText('%s')" % region
            queryString += " AND Area(Intersection(ic.border, %s)) / Area(ic.border) > %f " % (polygonString, minInter)
        queryString +=  " ORDER BY ic.sensstart "
        print '\nget_new_images queryString:\n\n%s\n\n\n' % queryString
        cur.execute(queryString)
        rows = cur.fetchall()
        cur.connection.commit()
        fields = [f[0] for f in cur.description]
        cur.connection.commit()
        cur = None
        return rows, fields

    def create_view(self):
        '''Create view from given fields'''
        self.viewName = '%s_view' % self.table
        if self.exist_table(self.viewName):
            print 'View %s already exsits' % self.viewName
        else:
            viewQuery = '''
                CREATE OR REPLACE VIEW %s AS
                SELECT ci.name, cp.name AS path, cs.name as sensor, ci.sensstart, ci.border
                ''' % self.viewName
            for fName in self.fields:
                viewQuery += ', cm.%s' % fName

            viewQuery += '''
                FROM %s AS cm
                JOIN cat_images as ci ON cm.image_id = ci.id
                JOIN cat_sensors as cs ON ci.sensor_id = cs.id
                JOIN cat_paths as cp ON ci.path_id = cp.id
            ''' % self.table
            print viewQuery
            cur = self.connect_postgresql().cursor()
            cur.execute(viewQuery)
            cur.connection.commit()
            cur = None

    def set_field_value(self, fileName, fieldName, fieldValue=1):
        'Set value of field'
        cur = self.connect_postgresql().cursor()
        # get id of the image in 'cat_images'
        catImagesExist, catImagesRow = self.exist_entry(cur, fileName, 'name', 'cat_images')
        catImagesID = catImagesRow[0]
        print 'catImagesRow', catImagesRow
        # get id of the image in self.table
        selTableExist, selTableRow = self.exist_entry(cur, catImagesID, fieldName='image_id')
        print 'selTableRow', selTableRow
        selfImageID = selTableRow[0]
        # update
        queryString = '''
            UPDATE %s
            SET %s=%s
            WHERE id = %d
            ''' % (self.table, fieldName, str(fieldValue), selfImageID)
        print 'queryString', queryString
        cur.execute(queryString)
        cur.connection.commit()
        cur = None

class FakeImage():
    '''Class with fake image wich support only get_metadata'''
    fakeImageDict = {}

    def __init__(self, fieldNames=None, fieldValues=None, fieldDict=None):
        '''Set metadata of the image'''
        if fieldDict is not None:
            for fName in fieldDict:
                self.set_metadata(fName, fieldDict[fName])
        else:
            for fName, fValue in zip(fieldNames, fieldValues):
                if fName != 'image_id' and fName != '':
                    self.set_metadata(fName, fValue)

    def get_metadata(self, metaName=None):
        '''Mimic Nansat.get_metadata()'''
        if metaName is None:
            return self.fakeImageDict
        else:
            return self.fakeImageDict[metaName]

    def set_metadata(self, metaName, metaValue):
        '''Mimic Nansat.set_metadat()'''
        if metaValue is None or metaValue == 'None':
            metaValue = 0
        self.fakeImageDict[metaName] = "'%s'" % metaValue

class WebDatabase(SimpleDatabase):
    ''' Connector to PostGIS database'''
    mimamo = {
        'any':    [ 1, 12],
        'winter': [ 1,  3],
        'spring': [ 4,  6],
        'summer': [ 7,  9],
        'autumn': [10, 12],
    }

    def __init__(self, table='cat_images'):
        '''Connect to the database'''
        self.table = table
        self.initialize()
        self.cur = self.connect_postgresql().cursor()

    def get_short_list(self, start_date, stop_date=None, season='any', mask='%', latlons=''):
        ''' Get list of files filtered by time and space'''
        if stop_date is None:
            stop_date = start_date
        start_date += ' 00:00:00'
        stop_date += ' 23:59:59'

        query =  " SELECT *, AsText(border) FROM %s AS tb1 WHERE sensstart >= '%s' AND sensstart <= '%s' " % (self.table, start_date, stop_date)
        query += " AND EXTRACT(MONTH FROM sensstart) BETWEEN %s AND %s " % (self.mimamo[season][0], self.mimamo[season][1])
        query += " AND name LIKE '%s' " % mask

        if len(latlons) > 0:
            latlonStr = latlons.replace(' ', '|').replace(',', '|').replace('[', '|').replace(']', '|')
            latlonList = latlonStr.split('|')
            lll = []
            for latlon in latlonList:
                if len(latlon) > 0:
                    lll.append(latlon)

            polyStr = "GeomFromText('POLYGON(("
            for i in range(0, len(lll), 2):
                polyStr += '%s %s, ' % (str(lll[i]), str(lll[i+1]))
            polyStr += '%s %s, ' % (str(lll[0]), str(lll[1]))
            polyStr = polyStr[:-2] + "))')"

            query += " AND Intersects(border, %s)" % polyStr

        query += " ORDER BY sensstart ";
        self.cur.execute(query)
        rows = self.cur.fetchall()
        self.cur.connection.commit()
        fields = [f[0] for f in self.cur.description]
        self.cur.connection.commit()
        return rows, fields, query

    def get_unique_dates(self, start_date, stop_date=None):
        '''Get list of unique dates for given period'''

        if stop_date is None:
            stop_date = start_date
        start_date += ' 00:00:00'
        stop_date += ' 23:59:59'

        query = '''SELECT DISTINCT date(sensstart) AS udate from %s
        WHERE sensstart >= '%s' AND sensstart <= '%s'
        ORDER BY udate''' % (self.table, start_date, stop_date)

        self.cur.execute(query)
        rows = self.cur.fetchall()
        self.cur.connection.commit()
        fields = [f[0] for f in self.cur.description]
        self.cur.connection.commit()
        return rows, fields, query


"""
// How to delete duplicates:
CREATE OR REPLACE VIEW cat_radarsat2ice_view_dup AS
 SELECT cat_radarsat2ice.image_id, count(cat_radarsat2ice.image_id) AS count
   FROM cat_radarsat2ice
  GROUP BY cat_radarsat2ice.image_id
 HAVING count(cat_radarsat2ice.image_id) > 1;

// =====
DELETE
FROM cat_radarsat2ice AS cm
USING cat_radarsat2ice_view_dup
WHERE cm.image_id = cat_radarsat2ice_view_dup.image_id;

"""

