from .data_type_classes import RevoUser, Advert, SQLAlchemyAdvert, SQLAlchemyUser, DeclarativeBase
from sqlalchemy import create_engine, func as sql_func, asc as sql_asc
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship, load_only
# from sqlalchemy.sql import func
import re
from datetime import datetime
import json

# base = declarative_base()


class DataBase:
    """Main class to encapsulate the DB functionality

    Right now mostly relying on SQL Alchemy
    """

    def __init__(self, dbName='revolico'):
        self.user = 'postgres'
        self.dbName = dbName
        self.password = 'root'
        self.host = 'localhost:5432'
        self.dbString = "postgres://{user}:{password}@{host}/{db}".format(
            user=self.user, password=self.password, host=self.host, db=self.dbName)
        self.cursor = create_engine(self.dbString)
        self.session = sessionmaker(self.cursor)()
        self.goodID = re.compile(r'\d{8,}')
        self.adType = Advert()
        self.userType = RevoUser()

    # ------ GENERAL SECTION -----------
    def write_element(self, idName, elemData, elemFields, elemClass):
        # Set the fields to their defaults in case they don't exist
        for field, fieldInfo in elemFields.items():
            if not field in elemData:
                elemData[field] = fieldInfo['default']

        DeclarativeBase.metadata.create_all(self.cursor)
        # If the ID is cero, auto increment it
        elemID = int(elemData[idName])
        if elemID == 0:
            try:
                elemID = self.session.query(sql_func.max(
                    getattr(elemClass, idName))).scalar() + 1
            except TypeError:
                elemID = 1
            elemData[idName] = elemID

        # Try to get the element by ID
        oldElem = self.session.query(elemClass).get(elemID)
        newElem = elemClass()
        # If the element exists only modify it
        if oldElem:
            for field in elemFields:
                setattr(oldElem, field, elemData[field])
        else:
            # If the element doesn't exist, you need to add it
            for field in elemFields:
                setattr(newElem, field, elemData[field])
            self.session.add(newElem)

        self.session.commit()

    def get_all_elements(self, elementClass):
        elements = self.session.query(elementClass).all()
        return elements

    def get_element_by_id(self, elemID, elemClass):
        return self.session.query(elemClass).get(elemID)

    def create_tables(self):
        DeclarativeBase.metadata.create_all(self.cursor)

    def delete_element(self, elemID, elementClass):
        if int(elemID) != 0:
            elem = self.session.query(elementClass).get(elemID)
            self.session.delete(elem)

    # ----- SECTION FOR ADS -------------

    def find_ads_by_title(self, title: str):
        ads = self.session.query(SQLAlchemyAdvert).filter(
            SQLAlchemyAdvert.title == title)
        adDicts = []
        if ads:
            adDicts = [self.advert_to_dic(ad) for ad in ads]
        return adDicts

    def write_ad(self, adDic: dict):
        # End early if the ID doesn't have a good format
        if not self.goodID.match(str(adDic['ad_id'])):
            return

        self.write_element('ad_id', adDic,
                           self.adType.fields, SQLAlchemyAdvert)

    def write_ads(self, adList: list):
        for ad in adList:
            self.write_ad(ad)

    def advert_to_dic(self, adObj: SQLAlchemyAdvert):
        adDic = {}
        for field in self.adType.fields:
            adDic[field] = getattr(adObj, field)
        return adDic

    def get_all_ads(self):
        return self.get_all_elements(SQLAlchemyAdvert)

    def get_ad_by_id(self, adID):
        return self.get_element_by_id(adID, SQLAlchemyAdvert)

    def delete_ad(self, adID):
        self.delete_element(adID, SQLAlchemyAdvert)
    # ---------- SECTION FOR USERS ------------

    def get_all_users(self):
        return self.get_all_elements(SQLAlchemyUser)

    def get_user_by_id(self, userID):
        return self.get_element_by_id(userID, SQLAlchemyUser)

    def write_user(self, userDic):
        self.write_element('user_id', userDic,
                           self.userType.fields, SQLAlchemyUser)

    def find_users_by_phone(self, phone):
        usersWithPhone = self.session.query(SQLAlchemyUser).filter(
            SQLAlchemyUser.phone_numbers.like('%' + phone + '%')).order_by('user_id')
        return usersWithPhone

    def delete_user(self, userID):
        self.delete_element(userID, SQLAlchemyUser)

    def get_users_ads(self, userID):
        ads = self.session.query(SQLAlchemyAdvert).join(
            SQLAlchemyUser).filter(SQLAlchemyUser.user_id == userID).all()
        return ads

    def count_users_ads(self, userID):
        adsAmount = self.session.query(SQLAlchemyAdvert).join(
            SQLAlchemyUser).filter(SQLAlchemyUser.user_id == userID).count()
        return adsAmount

a5e7182f7985d39a9bf642c4f015b47a4cca9e81
<mask token>


class DataBase:
    <mask token>
    <mask token>
    <mask token>
    <mask token>
    <mask token>
    <mask token>
    <mask token>

    def find_ads_by_title(self, title: str):
        ads = self.session.query(SQLAlchemyAdvert).filter(SQLAlchemyAdvert.
            title == title)
        adDicts = []
        if ads:
            adDicts = [self.advert_to_dic(ad) for ad in ads]
        return adDicts
    <mask token>

    def write_ads(self, adList: list):
        for ad in adList:
            self.write_ad(ad)

    def advert_to_dic(self, adObj: SQLAlchemyAdvert):
        adDic = {}
        for field in self.adType.fields:
            adDic[field] = getattr(adObj, field)
        return adDic
    <mask token>
    <mask token>

    def delete_ad(self, adID):
        self.delete_element(adID, SQLAlchemyAdvert)

    def get_all_users(self):
        return self.get_all_elements(SQLAlchemyUser)

    def get_user_by_id(self, userID):
        return self.get_element_by_id(userID, SQLAlchemyUser)

    def write_user(self, userDic):
        self.write_element('user_id', userDic, self.userType.fields,
            SQLAlchemyUser)
    <mask token>
    <mask token>

    def get_users_ads(self, userID):
        ads = self.session.query(SQLAlchemyAdvert).join(SQLAlchemyUser).filter(
            SQLAlchemyUser.user_id == userID).all()
        return ads
    <mask token>

<mask token>


class DataBase:
    <mask token>

    def __init__(self, dbName='revolico'):
        self.user = 'postgres'
        self.dbName = dbName
        self.password = 'root'
        self.host = 'localhost:5432'
        self.dbString = 'postgres://{user}:{password}@{host}/{db}'.format(user
            =self.user, password=self.password, host=self.host, db=self.dbName)
        self.cursor = create_engine(self.dbString)
        self.session = sessionmaker(self.cursor)()
        self.goodID = re.compile('\\d{8,}')
        self.adType = Advert()
        self.userType = RevoUser()
    <mask token>
    <mask token>
    <mask token>
    <mask token>
    <mask token>

    def find_ads_by_title(self, title: str):
        ads = self.session.query(SQLAlchemyAdvert).filter(SQLAlchemyAdvert.
            title == title)
        adDicts = []
        if ads:
            adDicts = [self.advert_to_dic(ad) for ad in ads]
        return adDicts
    <mask token>

    def write_ads(self, adList: list):
        for ad in adList:
            self.write_ad(ad)

    def advert_to_dic(self, adObj: SQLAlchemyAdvert):
        adDic = {}
        for field in self.adType.fields:
            adDic[field] = getattr(adObj, field)
        return adDic

    def get_all_ads(self):
        return self.get_all_elements(SQLAlchemyAdvert)
    <mask token>

    def delete_ad(self, adID):
        self.delete_element(adID, SQLAlchemyAdvert)

    def get_all_users(self):
        return self.get_all_elements(SQLAlchemyUser)

    def get_user_by_id(self, userID):
        return self.get_element_by_id(userID, SQLAlchemyUser)

    def write_user(self, userDic):
        self.write_element('user_id', userDic, self.userType.fields,
            SQLAlchemyUser)

    def find_users_by_phone(self, phone):
        usersWithPhone = self.session.query(SQLAlchemyUser).filter(
            SQLAlchemyUser.phone_numbers.like('%' + phone + '%')).order_by(
            'user_id')
        return usersWithPhone
    <mask token>

    def get_users_ads(self, userID):
        ads = self.session.query(SQLAlchemyAdvert).join(SQLAlchemyUser).filter(
            SQLAlchemyUser.user_id == userID).all()
        return ads

    def count_users_ads(self, userID):
        adsAmount = self.session.query(SQLAlchemyAdvert).join(SQLAlchemyUser
            ).filter(SQLAlchemyUser.user_id == userID).count()
        return adsAmount

<mask token>


class DataBase:
    <mask token>

    def __init__(self, dbName='revolico'):
        self.user = 'postgres'
        self.dbName = dbName
        self.password = 'root'
        self.host = 'localhost:5432'
        self.dbString = 'postgres://{user}:{password}@{host}/{db}'.format(user
            =self.user, password=self.password, host=self.host, db=self.dbName)
        self.cursor = create_engine(self.dbString)
        self.session = sessionmaker(self.cursor)()
        self.goodID = re.compile('\\d{8,}')
        self.adType = Advert()
        self.userType = RevoUser()

    def write_element(self, idName, elemData, elemFields, elemClass):
        for field, fieldInfo in elemFields.items():
            if not field in elemData:
                elemData[field] = fieldInfo['default']
        DeclarativeBase.metadata.create_all(self.cursor)
        elemID = int(elemData[idName])
        if elemID == 0:
            try:
                elemID = self.session.query(sql_func.max(getattr(elemClass,
                    idName))).scalar() + 1
            except TypeError:
                elemID = 1
            elemData[idName] = elemID
        oldElem = self.session.query(elemClass).get(elemID)
        newElem = elemClass()
        if oldElem:
            for field in elemFields:
                setattr(oldElem, field, elemData[field])
        else:
            for field in elemFields:
                setattr(newElem, field, elemData[field])
            self.session.add(newElem)
        self.session.commit()
    <mask token>
    <mask token>
    <mask token>
    <mask token>

    def find_ads_by_title(self, title: str):
        ads = self.session.query(SQLAlchemyAdvert).filter(SQLAlchemyAdvert.
            title == title)
        adDicts = []
        if ads:
            adDicts = [self.advert_to_dic(ad) for ad in ads]
        return adDicts

    def write_ad(self, adDic: dict):
        if not self.goodID.match(str(adDic['ad_id'])):
            return
        self.write_element('ad_id', adDic, self.adType.fields, SQLAlchemyAdvert
            )

    def write_ads(self, adList: list):
        for ad in adList:
            self.write_ad(ad)

    def advert_to_dic(self, adObj: SQLAlchemyAdvert):
        adDic = {}
        for field in self.adType.fields:
            adDic[field] = getattr(adObj, field)
        return adDic

    def get_all_ads(self):
        return self.get_all_elements(SQLAlchemyAdvert)
    <mask token>

    def delete_ad(self, adID):
        self.delete_element(adID, SQLAlchemyAdvert)

    def get_all_users(self):
        return self.get_all_elements(SQLAlchemyUser)

    def get_user_by_id(self, userID):
        return self.get_element_by_id(userID, SQLAlchemyUser)

    def write_user(self, userDic):
        self.write_element('user_id', userDic, self.userType.fields,
            SQLAlchemyUser)

    def find_users_by_phone(self, phone):
        usersWithPhone = self.session.query(SQLAlchemyUser).filter(
            SQLAlchemyUser.phone_numbers.like('%' + phone + '%')).order_by(
            'user_id')
        return usersWithPhone
    <mask token>

    def get_users_ads(self, userID):
        ads = self.session.query(SQLAlchemyAdvert).join(SQLAlchemyUser).filter(
            SQLAlchemyUser.user_id == userID).all()
        return ads

    def count_users_ads(self, userID):
        adsAmount = self.session.query(SQLAlchemyAdvert).join(SQLAlchemyUser
            ).filter(SQLAlchemyUser.user_id == userID).count()
        return adsAmount

<mask token>


class DataBase:
    <mask token>

    def __init__(self, dbName='revolico'):
        self.user = 'postgres'
        self.dbName = dbName
        self.password = 'root'
        self.host = 'localhost:5432'
        self.dbString = 'postgres://{user}:{password}@{host}/{db}'.format(user
            =self.user, password=self.password, host=self.host, db=self.dbName)
        self.cursor = create_engine(self.dbString)
        self.session = sessionmaker(self.cursor)()
        self.goodID = re.compile('\\d{8,}')
        self.adType = Advert()
        self.userType = RevoUser()

    def write_element(self, idName, elemData, elemFields, elemClass):
        for field, fieldInfo in elemFields.items():
            if not field in elemData:
                elemData[field] = fieldInfo['default']
        DeclarativeBase.metadata.create_all(self.cursor)
        elemID = int(elemData[idName])
        if elemID == 0:
            try:
                elemID = self.session.query(sql_func.max(getattr(elemClass,
                    idName))).scalar() + 1
            except TypeError:
                elemID = 1
            elemData[idName] = elemID
        oldElem = self.session.query(elemClass).get(elemID)
        newElem = elemClass()
        if oldElem:
            for field in elemFields:
                setattr(oldElem, field, elemData[field])
        else:
            for field in elemFields:
                setattr(newElem, field, elemData[field])
            self.session.add(newElem)
        self.session.commit()
    <mask token>

    def get_element_by_id(self, elemID, elemClass):
        return self.session.query(elemClass).get(elemID)

    def create_tables(self):
        DeclarativeBase.metadata.create_all(self.cursor)

    def delete_element(self, elemID, elementClass):
        if int(elemID) != 0:
            elem = self.session.query(elementClass).get(elemID)
            self.session.delete(elem)

    def find_ads_by_title(self, title: str):
        ads = self.session.query(SQLAlchemyAdvert).filter(SQLAlchemyAdvert.
            title == title)
        adDicts = []
        if ads:
            adDicts = [self.advert_to_dic(ad) for ad in ads]
        return adDicts

    def write_ad(self, adDic: dict):
        if not self.goodID.match(str(adDic['ad_id'])):
            return
        self.write_element('ad_id', adDic, self.adType.fields, SQLAlchemyAdvert
            )

    def write_ads(self, adList: list):
        for ad in adList:
            self.write_ad(ad)

    def advert_to_dic(self, adObj: SQLAlchemyAdvert):
        adDic = {}
        for field in self.adType.fields:
            adDic[field] = getattr(adObj, field)
        return adDic

    def get_all_ads(self):
        return self.get_all_elements(SQLAlchemyAdvert)

    def get_ad_by_id(self, adID):
        return self.get_element_by_id(adID, SQLAlchemyAdvert)

    def delete_ad(self, adID):
        self.delete_element(adID, SQLAlchemyAdvert)

    def get_all_users(self):
        return self.get_all_elements(SQLAlchemyUser)

    def get_user_by_id(self, userID):
        return self.get_element_by_id(userID, SQLAlchemyUser)

    def write_user(self, userDic):
        self.write_element('user_id', userDic, self.userType.fields,
            SQLAlchemyUser)

    def find_users_by_phone(self, phone):
        usersWithPhone = self.session.query(SQLAlchemyUser).filter(
            SQLAlchemyUser.phone_numbers.like('%' + phone + '%')).order_by(
            'user_id')
        return usersWithPhone

    def delete_user(self, userID):
        self.delete_element(userID, SQLAlchemyUser)

    def get_users_ads(self, userID):
        ads = self.session.query(SQLAlchemyAdvert).join(SQLAlchemyUser).filter(
            SQLAlchemyUser.user_id == userID).all()
        return ads

    def count_users_ads(self, userID):
        adsAmount = self.session.query(SQLAlchemyAdvert).join(SQLAlchemyUser
            ).filter(SQLAlchemyUser.user_id == userID).count()
        return adsAmount

from .data_type_classes import RevoUser, Advert, SQLAlchemyAdvert, SQLAlchemyUser, DeclarativeBase
from sqlalchemy import create_engine, func as sql_func, asc as sql_asc
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship, load_only
# from sqlalchemy.sql import func
import re
from datetime import datetime
import json

# base = declarative_base()


class DataBase:
    """Main class to encapsulate the DB functionality

    Right now mostly relying on SQL Alchemy
    """

    def __init__(self, dbName='revolico'):
        self.user = 'postgres'
        self.dbName = dbName
        self.password = 'root'
        self.host = 'localhost:5432'
        self.dbString = "postgres://{user}:{password}@{host}/{db}".format(
            user=self.user, password=self.password, host=self.host, db=self.dbName)
        self.cursor = create_engine(self.dbString)
        self.session = sessionmaker(self.cursor)()
        self.goodID = re.compile(r'\d{8,}')
        self.adType = Advert()
        self.userType = RevoUser()

    # ------ GENERAL SECTION -----------
    def write_element(self, idName, elemData, elemFields, elemClass):
        # Set the fields to their defaults in case they don't exist
        for field, fieldInfo in elemFields.items():
            if not field in elemData:
                elemData[field] = fieldInfo['default']

        DeclarativeBase.metadata.create_all(self.cursor)
        # If the ID is cero, auto increment it
        elemID = int(elemData[idName])
        if elemID == 0:
            try:
                elemID = self.session.query(sql_func.max(
                    getattr(elemClass, idName))).scalar() + 1
            except TypeError:
                elemID = 1
            elemData[idName] = elemID

        # Try to get the element by ID
        oldElem = self.session.query(elemClass).get(elemID)
        newElem = elemClass()
        # If the element exists only modify it
        if oldElem:
            for field in elemFields:
                setattr(oldElem, field, elemData[field])
        else:
            # If the element doesn't exist, you need to add it
            for field in elemFields:
                setattr(newElem, field, elemData[field])
            self.session.add(newElem)

        self.session.commit()

    def get_all_elements(self, elementClass):
        elements = self.session.query(elementClass).all()
        return elements

    def get_element_by_id(self, elemID, elemClass):
        return self.session.query(elemClass).get(elemID)

    def create_tables(self):
        DeclarativeBase.metadata.create_all(self.cursor)

    def delete_element(self, elemID, elementClass):
        if int(elemID) != 0:
            elem = self.session.query(elementClass).get(elemID)
            self.session.delete(elem)

    # ----- SECTION FOR ADS -------------

    def find_ads_by_title(self, title: str):
        ads = self.session.query(SQLAlchemyAdvert).filter(
            SQLAlchemyAdvert.title == title)
        adDicts = []
        if ads:
            adDicts = [self.advert_to_dic(ad) for ad in ads]
        return adDicts

    def write_ad(self, adDic: dict):
        # End early if the ID doesn't have a good format
        if not self.goodID.match(str(adDic['ad_id'])):
            return

        self.write_element('ad_id', adDic,
                           self.adType.fields, SQLAlchemyAdvert)

    def write_ads(self, adList: list):
        for ad in adList:
            self.write_ad(ad)

    def advert_to_dic(self, adObj: SQLAlchemyAdvert):
        adDic = {}
        for field in self.adType.fields:
            adDic[field] = getattr(adObj, field)
        return adDic

    def get_all_ads(self):
        return self.get_all_elements(SQLAlchemyAdvert)

    def get_ad_by_id(self, adID):
        return self.get_element_by_id(adID, SQLAlchemyAdvert)

    def delete_ad(self, adID):
        self.delete_element(adID, SQLAlchemyAdvert)
    # ---------- SECTION FOR USERS ------------

    def get_all_users(self):
        return self.get_all_elements(SQLAlchemyUser)

    def get_user_by_id(self, userID):
        return self.get_element_by_id(userID, SQLAlchemyUser)

    def write_user(self, userDic):
        self.write_element('user_id', userDic,
                           self.userType.fields, SQLAlchemyUser)

    def find_users_by_phone(self, phone):
        usersWithPhone = self.session.query(SQLAlchemyUser).filter(
            SQLAlchemyUser.phone_numbers.like('%' + phone + '%')).order_by('user_id')
        return usersWithPhone

    def delete_user(self, userID):
        self.delete_element(userID, SQLAlchemyUser)

    def get_users_ads(self, userID):
        ads = self.session.query(SQLAlchemyAdvert).join(
            SQLAlchemyUser).filter(SQLAlchemyUser.user_id == userID).all()
        return ads

    def count_users_ads(self, userID):
        adsAmount = self.session.query(SQLAlchemyAdvert).join(
            SQLAlchemyUser).filter(SQLAlchemyUser.user_id == userID).count()
        return adsAmount
