package io.nextop.v15.fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import io.nextop.NextopAndroid;
import io.nextop.v15.R;
import io.nextop.client.MessageControlState;
import rx.Observer;
import rx.android.schedulers.AndroidSchedulers;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class DebugMessagesFragment extends DebugChildFragment {
public static DebugMessagesFragment newInstance() {
return new DebugMessagesFragment();
}
private MessageAdapter messageAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_debug_messages, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
messageAdapter = new MessageAdapter();
View view = getView();
// FIXME header with spinner to set max network speed
// FIXME header option to go offline when online (TODO force attempt reconnect, surface connectivity)
ListView listView = (ListView) view.findViewById(R.id.list);
View profileHeader = LayoutInflater.from(view.getContext()).inflate(R.layout.view_debug_messages_header, listView, false);
listView.addHeaderView(profileHeader);
Spinner profileSpinner = (Spinner) profileHeader.findViewById(R.id.profile_spinner);
profileSpinner.setAdapter(new ProfileAdapter());
listView.setAdapter(messageAdapter);
bind(
NextopAndroid.getActive(getActivity()).getMessageControlState().getObservable()
// .subscribeOn(AndroidSchedulers.mainThread())
)
.throttleLast(200, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
.subscribe(messageAdapter);
}
final class MessageAdapter extends BaseAdapter implements Observer<MessageControlState> {
@Nullable
MessageControlState mcs = null;
// FIXME linger on remove, merge new state with lingering state
@Nullable
List<MessageControlState.GroupSnapshot> groups = null;
@Nullable
int[] groupNetSizes = null;
@Override
public void onNext(MessageControlState mcs) {
this.mcs = mcs;
if (null != mcs) {
groups = mcs.getGroups();
int n = groups.size();
groupNetSizes = new int[n + 1];
groupNetSizes[0] = 0;
for (int i = 0; i < n; ++i) {
groupNetSizes[i + 1] = groupNetSizes[i] + 1 + groups.get(i).entries.size();
}
} else {
groups = null;
groupNetSizes = null;
}
notifyDataSetChanged();
}
@Override
public void onCompleted() {
mcs = null;
groups = null;
groupNetSizes = null;
notifyDataSetChanged();
}
@Override
public void onError(Throwable e) {
mcs = null;
groups = null;
groupNetSizes = null;
notifyDataSetChanged();
}
@Override
public int getCount() {
return null != mcs ? groupNetSizes[groupNetSizes.length - 1] : 0;
}
@Override
public Object getItem(int position) {
// if (position < 0 || getCount() <= position) {
// throw new IndexOutOfBoundsException();
// }
int si = Arrays.binarySearch(groupNetSizes, position);
if (0 <= si) {
// a group
return groups.get(si);
} else if (0 < ~si) {
// an entry
int i = (~si) - 1;
return groups.get(i).entries.get(position - groupNetSizes[i] - 1);
} else {
throw new IllegalArgumentException();
}
}
@Override
public long getItemId(int position) {
// if (position < 0 || getCount() <= position) {
// throw new IndexOutOfBoundsException();
// }
// int si = Arrays.binarySearch(groupNetSizes, position);
// if (0 <= si) {
// // a group
// return groups.get(si).groupId.longHashCode();
// } else if (0 < ~si) {
// // an entry
// int i = (~si) - 1;
// return groups.get(i).entries.get(position - groupNetSizes[i] - 1).id.longHashCode();
// } else {
// throw new IllegalArgumentException();
// }
Object item = getItem(position);
if (item instanceof MessageControlState.GroupSnapshot) {
return ((MessageControlState.GroupSnapshot) item).groupId.longHashCode();
} else if (item instanceof MessageControlState.Entry) {
return ((MessageControlState.Entry) item).id.longHashCode();
} else {
throw new IllegalArgumentException();
}
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public int getItemViewType(int position) {
// if (position < 0 || getCount() <= position) {
// throw new IndexOutOfBoundsException();
// }
// int si = Arrays.binarySearch(groupNetSizes, position);
// if (0 <= si) {
// // a group
// return 0;
// } else if (0 < ~si) {
// // an entry
// return 1;
// } else {
// throw new IllegalArgumentException();
// }
Object item = getItem(position);
if (item instanceof MessageControlState.GroupSnapshot) {
return 0;
} else if (item instanceof MessageControlState.Entry) {
return 1;
} else {
throw new IllegalArgumentException();
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// FIXME
// FIXME
Object item = getItem(position);
if (item instanceof MessageControlState.GroupSnapshot) {
if (null == convertView) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_debug_messages_group, parent, false);
}
MessageControlState.GroupSnapshot groupSnapshot = (MessageControlState.GroupSnapshot) item;
TextView doctet1TextView = (TextView) convertView.findViewById(R.id.doctet1);
TextView doctet2TextView = (TextView) convertView.findViewById(R.id.doctet2);
TextView doctet3TextView = (TextView) convertView.findViewById(R.id.doctet3);
String idString = groupSnapshot.groupId.toString();
doctet1TextView.setText(idString.substring(0, 4));
doctet2TextView.setText(idString.substring(4, 8));
doctet3TextView.setText(idString.substring(8, 12));
return convertView;
} else if (item instanceof MessageControlState.Entry) {
if (null == convertView) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_debug_messages_entry, parent, false);
}
MessageControlState.Entry entry = (MessageControlState.Entry) item;
TextView routeTextView = (TextView) convertView.findViewById(R.id.route);
routeTextView.setText(String.format("%s %s", entry.message.route.target.method, entry.message.toUriString()));
return convertView;
} else {
throw new IllegalArgumentException();
}
}
}
private static class ProfileAdapter extends BaseAdapter {
@Override
public int getCount() {
return 4;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (null == convertView) {
convertView = convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_debug_messages_profile, parent, false);
}
ImageView imageView = (ImageView) convertView.findViewById(R.id.profile_image);
TextView profileTextView = (TextView) convertView.findViewById(R.id.profile_text);
switch (position) {
default:
case 0:
imageView.setVisibility(View.GONE);
profileTextView.setText("Current");
break;
case 1:
imageView.setVisibility(View.VISIBLE);
imageView.setImageResource(R.drawable.profile_0);
profileTextView.setText("31% of Users");
break;
case 2:
imageView.setVisibility(View.VISIBLE);
imageView.setImageResource(R.drawable.profile_1);
profileTextView.setText("57% of Users");
break;
case 3:
imageView.setVisibility(View.VISIBLE);
imageView.setImageResource(R.drawable.profile_2);
profileTextView.setText("12% of Users");
break;
}
return convertView;
}
}
}