'''
TODO: figure this out

Goal:
I want to make it easy to switch database implementations and include all of the data.

One might approach this task by simply writing a script that copies over all the data from the source database and
inserts it into the target, but that process is slow. By the time we've finished copying data, we will miss any records
that have been added or changed.

Basic idea:
- Change your create / update code to write the updated object into both databases (preserving IDs)
- Deploy that code - make sure that there is nothing running that might create data in only the source DB
- Bulk copy the rest of the data from source to target DB - don't overwrite anything in the target DB that might have
  gotten update while this bulk copy process is going on
- You can now point to the new target DB
- Delete the source DB and all its data (externally)

Downsides:
- Your code will run more slowly when writing to both source and target
- Might be some complexity with writing to both source and target - if one write fails for some reason, we need to make
  sure they both fail - may have to wrap with transations
- Don't muddy the neat and clean implementation with this very specific problem
'''



# To help you get started, here's what you've used successfully for pro-ipsi (statically though):

# from op_storage import factory

# data_types = [
#   'user',
#   'attorney',
#   'attorney_user',
#   'client',
#   'client_attorney',
#   'case',
#   'hearing',
#   'form',
#   'attorney_form',
#   'court',
#   'auth_code',
#   'obligation',
#   'obligation_reminder'
# ]

# rds_config = ...
# rds_db = factory.build('rds_data_postgres', rds_config)

# print('Initializing RDS...')
# for data_type in data_types:
#   rds_db.init(data_type)

# mongo_config = ...
# mongo_db = factory.build('mongo_db', mongo_config)

# print('Initializing MongoDB...')
# mongo_db._remove_indexes()
# mongo_db._remove_data_type('test_user')
# mongo_db._remove_data_type('!@#$%^&*():.,/')
# for data_type in data_types:
#   mongo_db._remove_data_type(data_type)
#   mongo_db.init(data_type)

# for data_type in data_types:
#   print('Copying data_type: ' + data_type)
#   to_copy = rds_db.list(data_type)
#   mongo_db._import_items(data_type, to_copy)

# print('Done')



from .abstract_base_store import AbstractBaseStore
from .factory import build


# Maybe something like this? This ensures that you're not accidentally interacting with only one of the DB instances
# since you won't even have an easily-accessible reference to it
# op_storage.factory.build(
#   'synchronized-compound-store',
#   {
#     'source_db_config': {
#       'type': ...,
#       'config': { ... }
#     },
#     'target_db_config': {
#       'type': ...,
#       'config': { ... }
#     }
#   }
# )


class SynchronizedCompoundStore(AbstractBaseStore):

  def __init__(self, source_db_config=None, target_db_config=None):
    self._source_db = build(source_db_config['type'], source_db_config['config'])
    self._target_db = build(target_db_config['type'], target_db_config['config'])

  # Override this so it initializes both DBs in the same way
  def init(self, data_type, indexes=[]):
    self._source_db.init(data_type, indexes=indexes)
    self._target_db.init(data_type, indexes=indexes)

  def create(self, data_type, data):
    data_id = self._source_db.create(data_type, data)
    self._target_db._create_or_update_with_id(data_type, data_id, data)
    return data_id

  def update(self, data_type, data_id, data):
    self._source_db.update(data_type, data_id, data)
    self._target_db._create_or_update_with_id(data_type, new_id, data)
