module profile.data;

import handy_http_primitives : Optional;
import streams.interfaces : InputStream;

import profile.model;

struct ProfileDownloadData {
    string filename;
    string contentType;
    ulong size;
    InputStream!ubyte inputStream;
}

/// Repository for interacting with the set of profiles belonging to a user.
interface ProfileRepository {
    Optional!Profile findByName(string name);
    Profile createProfile(string name);
    Profile[] findAll();
    void deleteByName(string name);
    ProfileDataSource getDataSource(in Profile profile);
    string getFilesPath(in Profile profile);
    Optional!ProfileDownloadData getProfileData(string name);
}

/// Repository for accessing the properties of a profile.
interface PropertiesRepository {
    Optional!string findProperty(string propertyName);
    void setProperty(string name, string value);
    void deleteProperty(string name);
    ProfileProperty[] findAll();
    void deleteAllByPrefix(string prefix);
}

/**
 * A data source for all data contained within a profile. This serves as the
 * gateway for all data access operations for a profile.
 */
interface ProfileDataSource {
    import account.data;
    import transaction.data;
    import attachment.data;
    import analytics.data;

    PropertiesRepository getPropertiesRepository();
    AttachmentRepository getAttachmentRepository();
    
    AccountRepository getAccountRepository();
    AccountJournalEntryRepository getAccountJournalEntryRepository();
    AccountValueRecordRepository getAccountValueRecordRepository();
    
    TransactionVendorRepository getTransactionVendorRepository();
    TransactionCategoryRepository getTransactionCategoryRepository();
    TransactionTagRepository getTransactionTagRepository();
    TransactionRepository getTransactionRepository();
    TransactionDraftRepository getTransactionDraftRepository();
    RecurringTransactionRepository getRecurringTransactionRepository();

    AnalyticsRepository getAnalyticsRepository();

    void doTransaction(void delegate () dg);
}

version(unittest) {
    class TestProfileDataSourceStub : ProfileDataSource {
        import account.data;
        import transaction.data;
        import attachment.data;
        import analytics.data;

        PropertiesRepository getPropertiesRepository() {
            throw new Exception("Not implemented");
        }
        AttachmentRepository getAttachmentRepository() {
            throw new Exception("Not implemented");
        }
        AccountRepository getAccountRepository() {
            throw new Exception("Not implemented");
        }
        AccountJournalEntryRepository getAccountJournalEntryRepository() {
            throw new Exception("Not implemented");
        }
        AccountValueRecordRepository getAccountValueRecordRepository() {
            throw new Exception("Not implemented");
        }
        TransactionVendorRepository getTransactionVendorRepository() {
            throw new Exception("Not implemented");
        }
        TransactionCategoryRepository getTransactionCategoryRepository() {
            throw new Exception("Not implemented");
        }
        TransactionTagRepository getTransactionTagRepository() {
            throw new Exception("Not implemented");
        }
        TransactionRepository getTransactionRepository() {
            throw new Exception("Not implemented");
        }
        TransactionDraftRepository getTransactionDraftRepository() {
            throw new Exception("Not implemented");
        }
        RecurringTransactionRepository getRecurringTransactionRepository() {
            throw new Exception("Not implemented");
        }
        AnalyticsRepository getAnalyticsRepository() {
            throw new Exception("Not implemented");
        }
        void doTransaction(void delegate () dg) {
            throw new Exception("Not implemented");
        }
    }
}
