/**
 * license: GPLv3
 reservationsystem
*/
package lodge.reservationsystem;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;

import lodge.datamodel.Account;
import lodge.datamodel.AccountList;
import lodge.datamodel.Address;
import lodge.datamodel.DuplicateObjectException;
import lodge.datamodel.EmailAddress;
import lodge.datamodel.IReservation;
import lodge.datamodel.IllegalOperationException;
import lodge.datamodel.Reservation;

public final class AccomodationManager {

    private final AccountList accounts = new AccountList();

    @SuppressWarnings("unused")
    private AccomodationManager() {
    };

    public AccomodationManager(String home) {
        setDataStoreRoot(home);
    };

    public final void setDataStoreRoot(String home) {
        DataRepository.setDataStoreRoot(home);
    }

    String getDataStoreRoot(){
        return DataRepository.getPath();
    }

    public final void loadAll()
            throws IOException, IllegalArgumentException, IllegalOperationException, DuplicateObjectException {
        accounts.clear();
        // walk directories
        Path rootDir = Paths.get(getDataStoreRoot());
        DataRepository.WalkFileSystemTree(this, rootDir);
        System.out.println(String.format("%s LoadAll Accounts %d", "Deserializing", accounts.size()));
    }

    // Load / Deserialize Account
    protected void load(Path file)
            throws IOException, IllegalArgumentException, IllegalOperationException, DuplicateObjectException {

        Account account = DataRepository.LoadAccount(file);
        if (account == null) {
            System.out.println(String.format("No Account: %s", file.toString()));
        } else {
            account.checkValid();
            accounts.add(account);
        }
    }

    public final List<Account> retrieveLoadedAccounts() {
        return Collections.unmodifiableList(accounts);
    }

    public Account retrieveAccount(String acct_id) {
        return accounts.find(acct_id);
    }

    public synchronized void AddAccount(final Account acct) throws Exception {
        accounts.add(acct);
    }

    public synchronized void UpdateAccount(final Account acct) throws Exception {
        if (acct != null) {
            accounts.save(acct);
        }
    }

    public final Account newAccount(String phone_number, Address mailing_address, EmailAddress email_address)
            throws Exception {
        Account acct = null;
        try {
            acct = new Account(phone_number, mailing_address, email_address);
        } catch (Exception e) {
            System.out.println(e.toString());
        }
        accounts.save(acct);
        return acct;
    }

    public boolean addReservation(final Account account, final Reservation reservation) {
        boolean result = account.add(reservation);
        return result;
    }

    public final Reservation findReservation(String reservation_number) {
        Reservation rsrv = null;
        for (Account acct : accounts) {
            rsrv = acct.findReservation(reservation_number);
            if (rsrv != null)
                break;
        }
        return rsrv;
    }

    public List<Account> getListOfAccounts() {
        return accounts.getListOfAccounts();
    }

    public List<? extends IReservation> getReservationList() {
        return accounts.getListOfReservations();
    }

    // Show all accounts lists of resverations
    public void showReservationList() {
        for (IReservation irsrv : accounts.getListOfReservations()) {
            System.out.println(String.format("Account %s: %s, %s", irsrv.getAccountNumber(),
                    irsrv.getReservation_number(), irsrv.getPhysical_address().getStreet()));
        }
    }

    // show the accounts
    public void showAccountList() {
        for (Account acct : accounts.getListOfAccounts()) {
            System.out.println(String.format("Account %s", acct.getAccount_number()));
        }
    }

    public final static class getRepositoryConfig {
        public final static String getPath() {
            String home = System.getenv("HOME") != null ? System.getenv("HOME")
                    : System.getenv("HOMEDRIVE") + System.getenv("HOMEPATH");
            return home.replace('\\', '/') + "/workspace/reservationsystem/src/resources";
        }
    }
}