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

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import java.util.ListIterator;

import lodge.reservation.Reservation;
import lodge.reservationsystem.DataRepository;
import lodge.reservation.IReservation;

public class Account {
        private String account_number = "-99";
        private String phone_number;
        private Address mailing_address;
        private EmailAddress email_address;
        private final AccountReservationList reservations = new AccountReservationList();

        public Account() {

        }

        public Account(
                        String account_number,
                        String phone_number,
                        Address mailing_address,
                        EmailAddress email_address) {
                this.account_number = account_number;
                this.phone_number = phone_number;
                this.mailing_address = mailing_address;
                this.email_address = email_address;
        }

        public Account(String phone_number, Address mailing_address, EmailAddress email_address) {
                this(AccountList.accountSerial(phone_number, mailing_address, email_address),
                                phone_number,
                                mailing_address,
                                email_address);
        }

        @Override
        public String toString() {

                StringBuilder sb = new StringBuilder();
                sb.append("{ \"Account\":{");
                sb.append("\"account_number\": \"").append(account_number).append("\",");
                sb.append("\"phone_number\": \"").append(phone_number).append("\",");
                sb.append("\"mailing_address\": ").append(mailing_address).append(",");
                sb.append("\"email_address\": ").append(email_address).append(",");
                sb.append(this.reservations.toString());
                sb.append("}}");
                return sb.toString();
        }

        public boolean add(Reservation rsrv) throws DuplicateObjectException {
                boolean result = false;
                if (rsrv == null) {
                        return false;
                }
                try {
                        result = reservations.add((IReservation) rsrv);
                } catch (DuplicateObjectException e) {
                        System.out.println(String.format("%s", e.getMessage()));
                } finally {
                }
                if (result) {
                        /* add account number to reservation for tracking purposes */
                        rsrv.setAccountNumber(this.account_number);
                }
                return result;
        }

        public static void Write(Account acct) throws IOException {
                String dataRoot = DataRepository.getPath();
                dataRoot = dataRoot + "/acc-" + acct.account_number + ".json";
                Path path = Paths.get(dataRoot);

                try (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
                        writer.write(acct.toString());
                        writer.flush();
                }

                for (IReservation i : acct.reservations) {
                        Reservation r = (Reservation) i;
                        r.Write(r);
                }
        }

        public String getAccount_number() {
                return account_number;
        }

        public void setAccount_number(String account_number) {
                this.account_number = account_number;
        }

        public String getPhone_number() {
                return phone_number;
        }

        public void setPhone_number(String phone_number) {
                this.phone_number = phone_number;
        }

        public Address getMailing_address() {
                return mailing_address;
        }

        public void setMailing_address(Address mailing_address) {
                this.mailing_address = mailing_address;
        }

        public EmailAddress getEmail_address() {
                return email_address;
        }

        public void setEmail_address(EmailAddress email_address) {
                this.email_address = email_address;
        }

        @Override
        public int hashCode() {
                final int prime = 31;
                int result = 1;
                result = prime * result + ((account_number == null) ? 0 : account_number.hashCode());
                return result;
        }

        public Reservation findReservation(String reservation_number) {
                return this.reservations.find(reservation_number);
        }

        @Override
        public boolean equals(Object obj) {
                if (this == obj)
                        return true;
                if (obj == null)
                        return false;
                if (getClass() != obj.getClass())
                        return false;
                Account other = (Account) obj;
                if (account_number == null) {
                        if (other.account_number != null)
                                return false;
                } else if (!account_number.equals(other.account_number))
                        return false;
                return true;
        }

        public void update(Account acct) {
                this.setEmail_address(acct.email_address);
                this.setPhone_number(acct.phone_number);
                this.setMailing_address(acct.mailing_address);
        }

        public ListIterator<IReservation> getAllReservations() {
                return this.reservations.listIterator();
        }

}