package net.heartshield.data;

import android.graphics.Bitmap;

import java.io.IOException;

/**
 * Interface to remote server and local storage.
 *
 * @author David Madl (git@abanbytes.eu)
 * @date 2016-04-07
 */
public interface IMeasurementDataManager {
    /** save a new measurement, and ask the remote server for the classification result */
    void create(Measurement measurement, MeasurementResultListener listener);

    void logFailure(Measurement measurement, MeasurementResultListener listener);

    void email(Measurement measurement, MeasurementResultListener listener);

    /** retrieve measurement from local storage */
    Measurement retrieve(MeasurementId id) throws IOException;

    byte[] retrieveAudio(MeasurementId id) throws IOException;

    /** update existing measurement (meta-data) */
    void update(Measurement measurement, MeasurementResultListener listener);

    /** list all measurements in ascending order (most recent last) */
    MeasurementSummary[] list();

    /** get report image that was transmitted by the server, or null if has no report image (yet) */
    Bitmap getReportImage(MeasurementId id);

    // these are internal, really. used for testing SyncTaskQueue.
    // TODO: extract into separate interface
    void createAndPost(String endpoint, Measurement measurement, MeasurementResultListener listener);
    void putRemoteAudio(final Measurement measurement, final MeasurementResultListener listener);
    boolean isBusy(Measurement measurement);
    void setBusy(Measurement measurement, boolean busy);
    void setBusyAudio(Measurement measurement, boolean busy);
    boolean removeFromCache(MeasurementId id) throws IOException;

    interface MeasurementResultListener {
        /** result is available from the server */
        void onResult(Measurement measurement);

        /** no result is available, e.g. connection or protocol error */
        void onError(Measurement measurement, ErrorCode code, String message);
    }

    interface PingResultListener {
        void onResult();
        void onError();
    }

    interface ActivationResultListener {
        void onResult(String appId);
        void onError(String reason);
    }

    void activate(String activationCode, ActivationResultListener listener);

    void ping(String appId, PingResultListener listener);

    interface MeasurementSummaryListener {
        void onMeasurementCreated(Measurement measurement);
        void onMeasurementUpdated(Measurement measurement);
    }
    void setSummaryListener(MeasurementSummaryListener listener);


    void setUseTestServer(boolean useTestServer);
    boolean isUnderTest();

    void startBackgroundThread();
    void stopBackgroundThread();

    // stops with stopBackgroundThread() after the current sync is done.
    void startBackgroundSync();

    interface SyncListener {
        /** called on start() and after every single measurement sync */
        void onProgress(int synced, int candidates);

        /** finished, whether completed or not */
        void onFinished(int synced, int candidates);
    }

    void setSyncListener(SyncListener listener);

    void addFailedMeasurement();
    int getNumFailedMeasurements();

    void logMessage(String appId, String mtype, String message);

    enum ErrorCode {
        LOCAL_ERROR,
        UNKNOWN_ERROR,
        CONNECTION_ERROR,
        HTTP_ERROR,
        PROTOCOL_ERROR
    }
}
