package com.openxc.enabler;

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

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.openxc.messages.CanMessage;

public class CanMessageAdapter extends BaseAdapter {
    final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();

    private Map<Integer, CanMessage> mMessages;
    private List<CanMessage> mValues;
    private Context mContext;

    public CanMessageAdapter(Context context) {
        mContext = context;
        mMessages = new LinkedHashMap<>();
    }

    public void add(CanMessage message) {
        ThreadPreconditions.checkOnMainThread();
        mMessages.put(message.getId(), message);
        mValues = new ArrayList<>(mMessages.values());
        Collections.sort(mValues);
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return mMessages.size();
    }

    @Override
    public CanMessage getItem(int position) {
        return mValues.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if(convertView == null) {
            convertView = LayoutInflater.from(mContext)
                    .inflate(R.layout.can_message_list_item, parent, false);
        }

        CanMessage message = getItem(position);

        TextView busView = (TextView) convertView.findViewById(R.id.can_message_bus);
        busView.setText("" + message.getBus());

        TextView idView = (TextView) convertView.findViewById(R.id.can_message_id);
        idView.setText("0x" + Integer.toHexString(message.getId()));

        TextView dataView = (TextView) convertView.findViewById(R.id.can_message_data);
        dataView.setText("0x" + bytesToHex(message.getData()));

        return convertView;
    }

    public static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for ( int j = 0; j < bytes.length; j++ ) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
}
}

@@ -84,37 +84,8 @@
 ns;%0A
-import java.util.Comparator;%0A
 impo
@@ -112,16 +112,16 @@
 ashMap;%0A
+
 import j
@@ -389,16 +389,138 @@
 Message;
+%0Aimport com.openxc.messages.ExactKeyMatcher;%0Aimport com.openxc.messages.KeyMatcher;%0Aimport com.openxc.messages.MessageKey;
 %0A%0Apublic
@@ -662,23 +662,26 @@
 ate Map%3C
-Integer
+MessageKey
 , CanMes
@@ -979,24 +979,112 @@
 inThread();%0A
+        MessageKey key = message.getKey();%0A        if(mMessages.containsKey(key)) %7B%0A    
         mMes
@@ -1093,31 +1093,523 @@
 ges.put(
+key, 
 message
-.getId()
+);%0A            // Already exists in values, just need to update it%0A            KeyMatcher exactMatcher = ExactKeyMatcher.buildExactMatcher(key);%0A            for(int i = 0; i %3C mValues.size(); i++) %7B%0A                if(exactMatcher.matches(mValues.get(i).getKey())) %7B%0A                    mValues.set(i, message);%0A                    break;%0A                %7D%0A            %7D%0A        %7D else %7B%0A            // Need to recreate values list because positions will be shifted%0A            mMessages.put(key
 , messag
@@ -1616,24 +1616,28 @@
 e);%0A        
+    
 mValues = ne
@@ -1679,16 +1679,20 @@
         
+    
 Collecti
@@ -1706,24 +1706,34 @@
 t(mValues);%0A
+        %7D%0A
         noti

Update CAN list view more efficiently, only re-build for new messages.