package com.openxc.enabler;

import android.util.Log;

import com.openxc.messages.ExactKeyMatcher;
import com.openxc.messages.KeyMatcher;
import com.openxc.messages.KeyedMessage;
import com.openxc.messages.MessageKey;
import com.openxc.messages.VehicleMessage;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

public abstract class KeyedMessageAdapter extends VehicleMessageAdapter {
    private Map<MessageKey, KeyedMessage> mMessages;

    public KeyedMessageAdapter() {
        mMessages = new LinkedHashMap<>();
    }

    public void add(KeyedMessage message) {
        ThreadPreconditions.checkOnMainThread();
        MessageKey key = message.getKey();
        boolean dataSetChanged = false;
        if(mMessages.containsKey(key)) {
            mMessages.put(key, message);
            // Already exists in values, just need to update it
            KeyMatcher exactMatcher = ExactKeyMatcher.buildExactMatcher(key);
            for(int i = 0; i < mValues.size(); i++) {
                KeyedMessage existingMessage = ((KeyedMessage)mValues.get(i));
                if(exactMatcher.matches(existingMessage.getKey())) {
                    mValues.set(i, message);
                    dataSetChanged |= shouldRefreshView(message, existingMessage);
                    break;
                }
            }
        } else {
            // Need to recreate values list because positions will be shifted
            mMessages.put(key, message);
            mValues = new ArrayList<VehicleMessage>(mMessages.values());
            Collections.sort(mValues);
            dataSetChanged = true;
        }

        if(dataSetChanged) {
            notifyDataSetChanged();
        }
    }

    /** Public: Determine if an update to a message should cause the view to be
     * refreshed.
     */
    public boolean shouldRefreshView(KeyedMessage message, KeyedMessage existingMessage) {
        // By default, we always refresh. Subclasses can do deeper inspection if
        // they want.
        Log.e("USB", "exception: " + message + existingMessage );
        return true;
    }
}
