#!/usr/bin/env python

import datetime, os
from sqlalchemy import *
from sqlalchemy import exceptions, sql
from sqlalchemy.orm import *
from sqlalchemy.orm.shard import ShardedSession
from sqlalchemy.sql import operators

from sqlalchemy import create_engine

from blog_engine import *
from lookup import Lookup
from post import Post

from elixir import *
import md5

from lookup_config import *

BUCKET = 2
DATA = 800
SHARD = 2


shard_post_dict={
    'shard1':'shard1',
    'shard2':'shard2'
}

sesslk = create_session_lookup()

def shard_chooser_post(mapper, instance, clause=None):

    querylk = sesslk.query(Lookup)
    print "inside shard_chooser_post"
    
    #HOW DOES IT KNOW WHICH BUCKET TO EXECUTE THE LOOKUP? 
    #function query_chooser_lookup  in module lookup_config.py maybe the problem
    #maybe query_chooser_lookup doesn't know 
    
    # This creates this kind of query: 
    #ShardedQuery: SELECT lookup.username AS lookup_username, lookup.shardname AS lookup_shardname 
    #FROM lookup ORDER BY lookup.username
    
    #Valid SQL Should be:
    #SELECT lookup.username AS lookup_username, lookup.shardname AS lookup_shardname 
    #FROM lookup  where lookup.username = "0" ;
    
    #What happend to instance.username is of Post.username
    lk_rec = querylk.get([instance.username])  #Bombing out on this line
    print lk_rec.shardname
    return shard_post_dict['%s' % lk_rec.shardname]


def id_chooser_post(query, ident):
    querylk = sesslk.query(Lookup)
    print "inside id_chooser_post"
    lk_rec = querylk.get([instance.username])
    print lk_rec.shardname
    return shard_post_dict['%s' % lk_rec.shardname]

def determine_post_shard(username):
    querylk = sesslk.query(Lookup)
    print "inside id_chooser_post"
    lk_rec = querylk.get([instance.username])
    print lk_rec.shardname
    return shard_post_dict['%s' % lk_rec.shardname]

def query_chooser_post(query):
    ids = []

    class FindPostShard(sql.ClauseVisitor):
        def visit_binary(self, binary):
            if binary.left is Post.username:
                if binary.operator == operators.eq:
                    ids.append(determine_post_shard[binary.right.value])
                elif binary.operator == operators.in_op:
                    for bind in binary.right.clauses:
                        ids.append(determine_post_shard[bind.value])
                    
    FindPostShard().traverse(query._criterion)
    if len(ids) == 0:
        return ['0', '1'] 
    else:
        return ids


create_session_post = sessionmaker(class_=ShardedSession, autoflush=True, transactional=True)
create_session_post.configure(shards={
    'shard1':shard1,
    'shard2':shard2
}, shard_chooser=shard_chooser_post, id_chooser=id_chooser_post, query_chooser=query_chooser_post)

#sess_post = create_session_post()
    
