import Realm from 'realm';

import { UserSchema, ProfileSchema, InvitesSchema, ContactsSchema, SignupConfig, AuthConfig, SessionSchema } from '../schemas/AuthSchema';

// ############################ MAIN #############################

var authRealm;
var signupRealm;
var sessionId;

// Loads the signup state; a `then` should be chained at the component level to save the state
export async function loadSignupState(screen) {
  const realm = await getRealm(screen);
  return getPreviousStateFor(screen, realm);
}

// Saves signup state for screens 1-5, we do not save 6 as the data loaded is random and should change everytime.
export async function saveSignupState(screen, state, isUpdate) {
  try {
    const realm = await getRealm(screen);
    realm.write(() => saveCurrentStateFor(screen, state, realm, isUpdate));
  } catch (error) {
    console.log(error);
  }
}

export function isContactSelected(recordID) {
  return signupRealm.objectForPrimaryKey(ContactsSchema.name, recordID);
}

export async function saveAuthState(sessionId) {
  try {
    const realm = await getRealm(0);
    realm.write(() => saveCurrentStateFor(0, { sessionId }, realm, !realm.empty));
  } catch (error) {
    console.log(error);
  }
}

export async function getAuthState() {
  if (!!sessionId) {
    return sessionId;
  }
  
  try {
    const realm = await getRealm(0);
    const auth = realm.objectForPrimaryKey(SessionSchema.name, primaryKey);
    sessionId = !!auth ? auth.sessionId : undefined;
    return sessionId;
  } catch (error) {
    console.log(error);
  }
}

// ############################ HELPERS #############################
async function getRealm(screen) {
  if (screen === 0) { 
    if (!authRealm) {
      authRealm = await Realm.open(AuthConfig);
    }
    return authRealm;
  } 

  if (!signupRealm) {
    signupRealm = await Realm.open(SignupConfig);
  }
  return signupRealm;
}

function getSchemaFor(screen) {
  if (screen === 0) {
    return SessionSchema;
  } else if (screen === 4) {
    return ProfileSchema;
  } else if (screen === 5) {
    return InvitesSchema;
  }

  return UserSchema;
}


function getPreviousStateFor(screen, realm) {
  let isUpdate  = true;
  let prevState = {};

  if (screen === 0) {
    prevState = realm.objectForPrimaryKey(SessionSchema.name, primaryKey);
    isUpdate = !!prevState;
  } else if (screen === 1) {
    prevState = realm.objectForPrimaryKey(UserSchema.name, primaryKey);
    isUpdate = !!prevState;
  } else if (screen === 2) {
    const object = realm.objectForPrimaryKey(UserSchema.name, primaryKey);
    if (!!object && !!object.tagferId) {
      const { tagferId, twitterUsername } = object;
      prevState = { tagferId, twitterUsername };
    }
  } else if (screen === 3) {
    const object = realm.objectForPrimaryKey(UserSchema.name, primaryKey);
    if (!!object && !!object.phoneNumber) {
      const { phoneNumber, cca2, callingCode } = object;
      prevState = { phoneNumber, cca2, callingCode };
    }
  } else if (screen === 4) {
    prevState = realm.objectForPrimaryKey(ProfileSchema.name, primaryKey);
    isUpdate = !!prevState;
  } else if (screen === 5) {
    isUpdate = !!realm.objectForPrimaryKey(InvitesSchema.name, primaryKey);
  } else if (screen === 6) {
    const user = realm.objectForPrimaryKey(UserSchema.name, primaryKey);
    const profile = realm.objectForPrimaryKey(ProfileSchema.name, primaryKey);
    const invites = realm.objectForPrimaryKey(InvitesSchema.name, primaryKey);
    prevState = { user, profile, invites };
  }

  return { isUpdate, prevState };
}

function saveCurrentStateFor(screen, state, realm, isUpdate) {
  if (screen === -5) {
    return saveSelectedContacts(realm, state);
  }

  const schema = getSchemaFor(screen);  
  try {
    realm.create(schema.name, { key: primaryKey, ...state }, isUpdate);
  } catch(error) {
    console.log(error);
  }
}

// NOTE: `selectedContacts` is an iterator passed from Map.keys()
function saveSelectedContacts(realm, selectedContacts) {
  realm.delete(realm.objects(ContactsSchema.name));

  for(let recordID of selectedContacts) {
    realm.create(ContactsSchema.name, { recordID });
  }
}

const primaryKey = 0;
