from typing import Union,Type
from abc import abstractmethod
import geoalchemy2 as ga
import sqlalchemy as sa
from sqlalchemy import Column,TIMESTAMP,Integer,Text,ARRAY,sql,REAL,ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship,backref
from sqlalchemy.schema import UniqueConstraint
from ..global_support import reprer
from .statuses import image_status

Base=declarative_base()

class StatusTrackable(object):
	status_key='status'

class Reconnectable(object):
	
	@abstractmethod
	def reconnect(self,session):
		pass

class KeysBase(Reconnectable):
	primary_keys=['id']
	
	def reconnect(self,session):
		pass
	
	def __repr__(self):
		return reprer(self)

class IntegerID_Base(KeysBase):
	id=Column(Integer,primary_key=True)

class TextID_Base(KeysBase):
	id=Column(Text,primary_key=True)

class SnowTest(Base,IntegerID_Base):
	__tablename__='snow_test'
	geom=Column(ga.Geometry('MULTIPOLYGON'))

class Cadastres_Info(Base,IntegerID_Base):
	__tablename__='cadastres_cadastre'
	kad_nomer=Column(Text)
	area=Column(REAL)
	geom=Column(ga.Geometry('MULTIPOLYGON'))
class Cadastres_Info2(Base,IntegerID_Base):
	__tablename__='cadastres_cadastre2'
	kad_nomer=Column(Text)
	area=Column(REAL)
	geom=Column(ga.Geometry('MULTIPOLYGON'))

class MainRequest(Base,IntegerID_Base,StatusTrackable):
	status_key='back_status'
	__tablename__='main_requests_request'
	request_date=Column(TIMESTAMP(True),server_default=sql.func.now())
	image_date=Column(TIMESTAMP(True),server_default=None)
	user_id=Column(Integer)
	order_request_date=Column(sa.Date,server_default=None)
	cadastre_id=Column(Integer)
	cadastre_value=Column(ga.Geometry('MULTIPOLYGON'))
	status=Column(Integer)
	status_changer=Column(Integer,default=0)
	back_status=Column(Text,default=image_status.Unprocessed)
	last_lookup_date=Column(TIMESTAMP(True),server_default=None)
	product_ids=Column(ARRAY(Text),server_default=None)
	results_dir=Column(Text,server_default=None)
	priority=Column(Integer,default=5)

class ImageDateChecker(Base,IntegerID_Base,StatusTrackable):
	status_key='image_date_checker_status'
	__tablename__='main_requests_imagedate'
	image_date=Column(TIMESTAMP(timezone=True))
	request_id=Column(Integer,ForeignKey(f'{MainRequest.__tablename__}.id'))
	cadastre_value=Column(ga.Geometry('MULTIPOLYGON'))
	image_date_checker_status=Column(Text)
	priority=Column(Integer,default=5)
	
	backend_request=relationship(MainRequest,uselist=False,backref=backref('image_date_request',cascade='all,delete'))

class User(Base,IntegerID_Base):
	__tablename__='auth_user'
	password=Column(sa.VARCHAR(128))
	last_login=Column(TIMESTAMP(timezone=True))
	is_superuser=Column(sa.Boolean,server_default='f')
	username=Column(sa.VARCHAR(150))
	first_name=Column(sa.VARCHAR(30))
	last_name=Column(sa.VARCHAR(150))
	email=Column(sa.VARCHAR(254))
	is_staff=Column(sa.Boolean,server_default='f')
	is_active=Column(sa.Boolean,server_default='t')
	date_joined=Column(TIMESTAMP(timezone=True))

class MeteoData(Base,KeysBase):
	__tablename__='meteo_data'
	primary_keys=['geometry','forecast_date']
	geometry=Column(ga.Geometry('POINT'),primary_key=True)
	forecast_date=Column(TIMESTAMP(timezone=True),primary_key=True)
	__table_args__=(UniqueConstraint('geometry','forecast_date',name='Unique_date_and_location'),)

class Sentinel2_Info(TextID_Base,Base,StatusTrackable):
	__tablename__='sentinel2_info'
	image_date=Column(TIMESTAMP(timezone=True))
	download_date=Column(TIMESTAMP(timezone=True))
	product_path_l1c=Column(Text,server_default=None)
	zip_path=Column(Text)
	product_path_l2a=Column(Text,server_default=None)
	status=Column(Text,server_default=image_status.Unprocessed)
	priority=Column(Integer,default=5)

# common_type=Union[Type[KeysBase],Type[Reconnectable]]

def main():
	# Sentinel2_Info.__table__.create(engine)
	pass
	# old_statuses=collections.OrderedDict()
	# old_statuses['RunningAtmosphericCorrection']=image_status.Running.AtmosphericCorrection
	# old_statuses['FinishedAtmosphericCorrection']=image_status.Finished.AtmosphericCorrection
	# old_statuses['QueuedForAtmosphericCorrection']=image_status.QueuedFor.AtmosphericCorrection
	# old_statuses['NotForProcessing']=image_status.NotForProcessing
	#
	# for old_status,new_status in old_statuses.items():
	# 	for row in session.query(Sentinel2_Info).filter(Sentinel2_Info.status==old_status).all():
	# 		row.status=new_status
	pass
	
	pass

if __name__=='__main__':
	main()
