package org.telegram.ui;

import android.animation.ObjectAnimator;
import android.animation.StateListAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.graphics.Outline;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.text.SpannableString;
import android.text.style.ImageSpan;
import android.util.SparseArray;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;

import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.support.widget.LinearLayoutManager;
import org.telegram.messenger.support.widget.RecyclerView;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.RequestDelegate;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ActionBar.ThemeDescription;
import org.telegram.ui.Cells.LoadingCell;
import org.telegram.ui.Cells.LocationCell;
import org.telegram.ui.Cells.ProfileSearchCell;
import org.telegram.ui.Cells.TextInfoPrivacyCell;
import org.telegram.ui.Components.CombinedDrawable;
import org.telegram.ui.Components.EmptyTextProgressView;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.voip.VoIPHelper;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class CallLogActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {

	private ListAdapter listViewAdapter;
	private EmptyTextProgressView emptyView;
	private LinearLayoutManager layoutManager;
	private RecyclerListView listView;
	private ImageView floatingButton;

	private ArrayList<CallLogRow> calls = new ArrayList<>();
	private boolean loading;
	private boolean firstLoaded;
	private boolean endReached;

	private int prevPosition;
	private int prevTop;
	private boolean scrollUpdated;
	private boolean floatingHidden;
	private final AccelerateDecelerateInterpolator floatingInterpolator = new AccelerateDecelerateInterpolator();

	private Drawable greenDrawable;
	private Drawable greenDrawable2;
	private Drawable redDrawable;
	private ImageSpan iconOut, iconIn, iconMissed;
	private TLRPC.User lastCallUser;

	private static final int TYPE_OUT = 0;
	private static final int TYPE_IN = 1;
	private static final int TYPE_MISSED = 2;

	@Override
	@SuppressWarnings("unchecked")
	public void didReceivedNotification(int id, int account, Object... args) {
		if (id == NotificationCenter.didReceivedNewMessages && firstLoaded) {
			ArrayList<MessageObject> arr = (ArrayList<MessageObject>) args[1];
			for (MessageObject msg : arr) {
				if (msg.messageOwner.action != null && msg.messageOwner.action instanceof TLRPC.TL_messageActionPhoneCall) {
					int userID = msg.messageOwner.from_id == UserConfig.getInstance(currentAccount).getClientUserId() ? msg.messageOwner.to_id.user_id : msg.messageOwner.from_id;
					int callType = msg.messageOwner.from_id == UserConfig.getInstance(currentAccount).getClientUserId() ? TYPE_OUT : TYPE_IN;
					TLRPC.PhoneCallDiscardReason reason = msg.messageOwner.action.reason;
					if (callType == TYPE_IN && (reason instanceof TLRPC.TL_phoneCallDiscardReasonMissed || reason instanceof TLRPC.TL_phoneCallDiscardReasonBusy)) {
						callType = TYPE_MISSED;
					}
					if (calls.size() > 0) {
						CallLogRow topRow = calls.get(0);
						if (topRow.user.id == userID && topRow.type == callType) {
							topRow.calls.add(0, msg.messageOwner);
							listViewAdapter.notifyItemChanged(0);
							continue;
						}
					}
					CallLogRow row = new CallLogRow();
					row.calls = new ArrayList<>();
					row.calls.add(msg.messageOwner);
					row.user = MessagesController.getInstance(currentAccount).getUser(userID);
					row.type = callType;
					calls.add(0, row);
					listViewAdapter.notifyItemInserted(0);
				}
			}
		} else if (id == NotificationCenter.messagesDeleted && firstLoaded) {
			boolean didChange = false;
			ArrayList<Integer> ids = (ArrayList<Integer>) args[0];
			Iterator<CallLogRow> itrtr = calls.iterator();
			while (itrtr.hasNext()) {
				CallLogRow row = itrtr.next();
				Iterator<TLRPC.Message> msgs = row.calls.iterator();
				while (msgs.hasNext()) {
					TLRPC.Message msg = msgs.next();
					if (ids.contains(msg.id)) {
						didChange = true;
						msgs.remove();
					}
				}
				if (row.calls.size() == 0)
					itrtr.remove();
			}
			if (didChange && listViewAdapter != null)
				listViewAdapter.notifyDataSetChanged();
		}
	}

	private class CustomCell extends FrameLayout {

		public CustomCell(Context context) {
			super(context);
		}
	}

	private View.OnClickListener callBtnClickListener = new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			CallLogRow row = (CallLogRow) v.getTag();
			VoIPHelper.startCall(lastCallUser = row.user, getParentActivity(), null);
		}
	};

	@Override
	public boolean onFragmentCreate() {
		super.onFragmentCreate();
		getCalls(0, 50);

		NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.didReceivedNewMessages);
		NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagesDeleted);

		return true;
	}

	@Override
	public void onFragmentDestroy() {
		super.onFragmentDestroy();
		NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.didReceivedNewMessages);
		NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagesDeleted);
	}

	@Override
	public View createView(Context context) {
		greenDrawable = getParentActivity().getResources().getDrawable(R.drawable.ic_call_made_green_18dp).mutate();
		greenDrawable.setBounds(0, 0, greenDrawable.getIntrinsicWidth(), greenDrawable.getIntrinsicHeight());
		greenDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_calls_callReceivedGreenIcon), PorterDuff.Mode.MULTIPLY));
		iconOut = new ImageSpan(greenDrawable, ImageSpan.ALIGN_BOTTOM);
		greenDrawable2 = getParentActivity().getResources().getDrawable(R.drawable.ic_call_received_green_18dp).mutate();
		greenDrawable2.setBounds(0, 0, greenDrawable2.getIntrinsicWidth(), greenDrawable2.getIntrinsicHeight());
		greenDrawable2.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_calls_callReceivedGreenIcon), PorterDuff.Mode.MULTIPLY));
		iconIn = new ImageSpan(greenDrawable2, ImageSpan.ALIGN_BOTTOM);
		redDrawable = getParentActivity().getResources().getDrawable(R.drawable.ic_call_received_green_18dp).mutate();
		redDrawable.setBounds(0, 0, redDrawable.getIntrinsicWidth(), redDrawable.getIntrinsicHeight());
		redDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_calls_callReceivedRedIcon), PorterDuff.Mode.MULTIPLY));
		iconMissed = new ImageSpan(redDrawable, ImageSpan.ALIGN_BOTTOM);

		actionBar.setBackButtonImage(R.drawable.ic_ab_back);
		actionBar.setAllowOverlayTitle(true);
		actionBar.setTitle(LocaleController.getString("Calls", R.string.Calls));
		actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
			@Override
			public void onItemClick(int id) {
				if (id == -1) {
					finishFragment();
				}
			}
		});

		fragmentView = new FrameLayout(context);
		fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
		FrameLayout frameLayout = (FrameLayout) fragmentView;

		emptyView = new EmptyTextProgressView(context);
		emptyView.setText(LocaleController.getString("NoCallLog", R.string.NoCallLog));
		frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));

		listView = new RecyclerListView(context);
		listView.setEmptyView(emptyView);
		listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false));
		listView.setAdapter(listViewAdapter = new ListAdapter(context));
		listView.setVerticalScrollbarPosition(LocaleController.isRTL ? RecyclerListView.SCROLLBAR_POSITION_LEFT : RecyclerListView.SCROLLBAR_POSITION_RIGHT);
		frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));

		listView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() {
			@Override
			public void onItemClick(View view, int position) {
				if (position < 0 || position >= calls.size()) {
					return;
				}
				CallLogRow row = calls.get(position);
				Bundle args = new Bundle();
				args.putInt("user_id", row.user.id);
				args.putInt("message_id", row.calls.get(0).id);
				NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats);
				presentFragment(new ChatActivity(args), true);
			}
		});
		listView.setOnItemLongClickListener(new RecyclerListView.OnItemLongClickListener() {
			@Override
			public boolean onItemClick(View view, final int position) {
				if (position < 0 || position >= calls.size()) {
					return false;
				}
				final CallLogRow row = calls.get(position);
				ArrayList<String> items = new ArrayList<>();
				items.add(LocaleController.getString("Delete", R.string.Delete));
				if (VoIPHelper.canRateCall((TLRPC.TL_messageActionPhoneCall) row.calls.get(0).action)) {
					items.add(LocaleController.getString("CallMessageReportProblem", R.string.CallMessageReportProblem));
				}
				new AlertDialog.Builder(getParentActivity())
						.setTitle(LocaleController.getString("Calls", R.string.Calls))
						.setItems(items.toArray(new String[items.size()]), new DialogInterface.OnClickListener() {
							@Override
							public void onClick(DialogInterface dialog, int which) {
								switch (which) {
									case 0:
										confirmAndDelete(row);
										break;
									case 1:
										VoIPHelper.showRateAlert(getParentActivity(), (TLRPC.TL_messageActionPhoneCall) row.calls.get(0).action);
										break;
								}
							}
						})
						.show();
				return true;
			}
		});
		listView.setOnScrollListener(new RecyclerView.OnScrollListener() {
			@Override
			public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
				int firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
				int visibleItemCount = firstVisibleItem == RecyclerView.NO_POSITION ? 0 : Math.abs(layoutManager.findLastVisibleItemPosition() - firstVisibleItem) + 1;
				if (visibleItemCount > 0) {
					int totalItemCount = listViewAdapter.getItemCount();
					if (!endReached && !loading && !calls.isEmpty() && firstVisibleItem + visibleItemCount >= totalItemCount - 5) {
						final CallLogRow row = calls.get(calls.size() - 1);
						AndroidUtilities.runOnUIThread(new Runnable() {
							@Override
							public void run() {
								getCalls(row.calls.get(row.calls.size() - 1).id, 100);
							}
						});
					}
				}

				if (floatingButton.getVisibility() != View.GONE) {
					final View topChild = recyclerView.getChildAt(0);
					int firstViewTop = 0;
					if (topChild != null) {
						firstViewTop = topChild.getTop();
					}
					boolean goingDown;
					boolean changed = true;
					if (prevPosition == firstVisibleItem) {
						final int topDelta = prevTop - firstViewTop;
						goingDown = firstViewTop < prevTop;
						changed = Math.abs(topDelta) > 1;
					} else {
						goingDown = firstVisibleItem > prevPosition;
					}
					if (changed && scrollUpdated) {
						hideFloatingButton(goingDown);
					}
					prevPosition = firstVisibleItem;
					prevTop = firstViewTop;
					scrollUpdated = true;
				}
			}
		});

		if (loading) {
			emptyView.showProgress();
		} else {
			emptyView.showTextView();
		}


		floatingButton = new ImageView(context);
		floatingButton.setVisibility(View.VISIBLE);
		floatingButton.setScaleType(ImageView.ScaleType.CENTER);

		Drawable drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), Theme.getColor(Theme.key_chats_actionBackground), Theme.getColor(Theme.key_chats_actionPressedBackground));
		if (Build.VERSION.SDK_INT < 21) {
			Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.floating_shadow).mutate();
			shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY));
			CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0);
			combinedDrawable.setIconSize(AndroidUtilities.dp(56), AndroidUtilities.dp(56));
			drawable = combinedDrawable;
		}
		floatingButton.setBackgroundDrawable(drawable);
		floatingButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_actionIcon), PorterDuff.Mode.MULTIPLY));
		floatingButton.setImageResource(R.drawable.ic_call_white_24dp);
		if (Build.VERSION.SDK_INT >= 21) {
			StateListAnimator animator = new StateListAnimator();
			animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(floatingButton, "translationZ", AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200));
			animator.addState(new int[]{}, ObjectAnimator.ofFloat(floatingButton, "translationZ", AndroidUtilities.dp(4), AndroidUtilities.dp(2)).setDuration(200));
			floatingButton.setStateListAnimator(animator);
			floatingButton.setOutlineProvider(new ViewOutlineProvider() {
				@SuppressLint("NewApi")
				@Override
				public void getOutline(View view, Outline outline) {
					outline.setOval(0, 0, AndroidUtilities.dp(56), AndroidUtilities.dp(56));
				}
			});
		}
		frameLayout.addView(floatingButton, LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 56 : 60, Build.VERSION.SDK_INT >= 21 ? 56 : 60, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.BOTTOM, LocaleController.isRTL ? 14 : 0, 0, LocaleController.isRTL ? 0 : 14, 14));
		floatingButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				Bundle args = new Bundle();
				args.putBoolean("destroyAfterSelect", true);
				args.putBoolean("returnAsResult", true);
				args.putBoolean("onlyUsers", true);
				ContactsActivity contactsFragment = new ContactsActivity(args);
				contactsFragment.setDelegate(new ContactsActivity.ContactsActivityDelegate() {
					@Override
					public void didSelectContact(TLRPC.User user, String param, ContactsActivity activity) {
						VoIPHelper.startCall(user, getParentActivity(), null);
					}
				});
				presentFragment(contactsFragment);
			}
		});

		return fragmentView;
	}

	private void hideFloatingButton(boolean hide) {
		if (floatingHidden == hide) {
			return;
		}
		floatingHidden = hide;
		ObjectAnimator animator = ObjectAnimator.ofFloat(floatingButton, "translationY", floatingHidden ? AndroidUtilities.dp(100) : 0).setDuration(300);
		animator.setInterpolator(floatingInterpolator);
		floatingButton.setClickable(!hide);
		animator.start();
	}

	private void getCalls(int max_id, final int count) {
		if (loading) {
			return;
		}
		loading = true;
		if (emptyView != null && !firstLoaded) {
			emptyView.showProgress();
		}
		if (listViewAdapter != null) {
			listViewAdapter.notifyDataSetChanged();
		}
		TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
		req.limit = count;
		req.peer = new TLRPC.TL_inputPeerEmpty();
		req.filter = new TLRPC.TL_inputMessagesFilterPhoneCalls();
		req.q = "";
		req.offset_id = max_id;
		int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, new RequestDelegate() {
			@Override
			public void run(final TLObject response, final TLRPC.TL_error error) {
				AndroidUtilities.runOnUIThread(new Runnable() {
					@Override
					public void run() {
						if (error == null) {
							SparseArray<TLRPC.User> users = new SparseArray<>();
							TLRPC.messages_Messages msgs = (TLRPC.messages_Messages) response;
							endReached = msgs.messages.isEmpty();
							for (int a = 0; a < msgs.users.size(); a++) {
								TLRPC.User user = msgs.users.get(a);
								users.put(user.id, user);
							}
							CallLogRow currentRow = calls.size() > 0 ? calls.get(calls.size() - 1) : null;
							for (int a = 0; a < msgs.messages.size(); a++) {
								TLRPC.Message msg = msgs.messages.get(a);
								if (msg.action == null || msg.action instanceof TLRPC.TL_messageActionHistoryClear) {
									continue;
								}
								int callType = msg.from_id == UserConfig.getInstance(currentAccount).getClientUserId() ? TYPE_OUT : TYPE_IN;
								TLRPC.PhoneCallDiscardReason reason = msg.action.reason;
								if (callType == TYPE_IN && (reason instanceof TLRPC.TL_phoneCallDiscardReasonMissed || reason instanceof TLRPC.TL_phoneCallDiscardReasonBusy)) {
									callType = TYPE_MISSED;
								}
								int userID = msg.from_id == UserConfig.getInstance(currentAccount).getClientUserId() ? msg.to_id.user_id : msg.from_id;
								if (currentRow == null || currentRow.user.id != userID || currentRow.type != callType) {
									if (currentRow != null && !calls.contains(currentRow)) {
										calls.add(currentRow);
									}
									CallLogRow row = new CallLogRow();
									row.calls = new ArrayList<>();
									row.user = users.get(userID);
									row.type = callType;
									currentRow = row;
								}
								currentRow.calls.add(msg);
							}
							if (currentRow != null && currentRow.calls.size() > 0 && !calls.contains(currentRow)) {
								calls.add(currentRow);
							}
						} else {
							endReached = true;
						}
						loading = false;
						firstLoaded = true;
						if (emptyView != null) {
							emptyView.showTextView();
						}
						if (listViewAdapter != null) {
							listViewAdapter.notifyDataSetChanged();
						}
					}
				});
			}
		}, ConnectionsManager.RequestFlagFailOnServerErrors);
		ConnectionsManager.getInstance(currentAccount).bindRequestToGuid(reqId, classGuid);
	}

	private void confirmAndDelete(final CallLogRow row) {
		if (getParentActivity() == null)
			return;
		new AlertDialog.Builder(getParentActivity())
				.setTitle(LocaleController.getString("AppName", R.string.AppName))
				.setMessage(LocaleController.getString("ConfirmDeleteCallLog", R.string.ConfirmDeleteCallLog))
				.setPositiveButton(LocaleController.getString("Delete", R.string.Delete), new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						ArrayList<Integer> ids = new ArrayList<>();
						for (TLRPC.Message msg : row.calls) {
							ids.add(msg.id);
						}
						MessagesController.getInstance(currentAccount).deleteMessages(ids, null, null, 0, false);
					}
				})
				.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null)
				.show()
				.setCanceledOnTouchOutside(true);
	}

	@Override
	public void onResume() {
		super.onResume();
		if (listViewAdapter != null) {
			listViewAdapter.notifyDataSetChanged();
		}
	}

	@Override
	public void onRequestPermissionsResultFragment(int requestCode, String[] permissions, int[] grantResults) {
		if (requestCode == 101) {
			if(grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
				VoIPHelper.startCall(lastCallUser, getParentActivity(), null);
			}else{
				VoIPHelper.permissionDenied(getParentActivity(), null);
			}
		}
	}

	private class ListAdapter extends RecyclerListView.SelectionAdapter {

		private Context mContext;

		public ListAdapter(Context context) {
			mContext = context;
		}

		@Override
		public boolean isEnabled(RecyclerView.ViewHolder holder) {
			return holder.getAdapterPosition() != calls.size();
		}

		@Override
		public int getItemCount() {
			int count = calls.size();
			if (!calls.isEmpty()) {
				if (!endReached) {
					count++;
				}
			}
			return count;
		}

		@Override
		public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
			View view;
			switch (viewType) {
				case 0:
					CustomCell frameLayout = new CustomCell(mContext);
					frameLayout.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));

					ProfileSearchCell cell = new ProfileSearchCell(mContext);
					cell.setPaddingRight(AndroidUtilities.dp(32));
					frameLayout.addView(cell);

					ImageView imageView = new ImageView(mContext);
					imageView.setImageResource(R.drawable.profile_phone);
					imageView.setAlpha(214);
					imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.MULTIPLY));
					imageView.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_AUDIO_SELECTOR_COLOR, 0));
					imageView.setScaleType(ImageView.ScaleType.CENTER);
					imageView.setOnClickListener(callBtnClickListener);
					frameLayout.addView(imageView, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, 8, 0, 8, 0));

					view = frameLayout;
					view.setTag(new ViewItem(imageView, cell));
					break;
				case 1:
					view = new LoadingCell(mContext);
					view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
					break;
				case 2:
				default:
					view = new TextInfoPrivacyCell(mContext);
					view.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
					break;
			}
			return new RecyclerListView.Holder(view);
		}

		@Override
		public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
			if (holder.getItemViewType() == 0) {
				ViewItem viewItem = (ViewItem) holder.itemView.getTag();
				ProfileSearchCell cell = viewItem.cell;
				CallLogRow row = calls.get(position);
				TLRPC.Message last = row.calls.get(0);
				SpannableString subtitle;
				String ldir = LocaleController.isRTL ? "\u202b" : "";
				if (row.calls.size() == 1) {
					subtitle = new SpannableString(ldir + "  " + LocaleController.formatDateCallLog(last.date));
				} else {
					subtitle = new SpannableString(String.format(ldir + "  (%d) %s", row.calls.size(), LocaleController.formatDateCallLog(last.date)));
				}
				switch (row.type) {
					case TYPE_OUT:
						subtitle.setSpan(iconOut, ldir.length(), ldir.length() + 1, 0);
						break;
					case TYPE_IN:
						subtitle.setSpan(iconIn, ldir.length(), ldir.length() + 1, 0);
						break;
					case TYPE_MISSED:
						subtitle.setSpan(iconMissed, ldir.length(), ldir.length() + 1, 0);
						break;
				}
				cell.setData(row.user, null, null, subtitle, false, false);
				cell.useSeparator = position != calls.size() - 1 || !endReached;
				viewItem.button.setTag(row);
			}
		}

		@Override
		public int getItemViewType(int i) {
			if (i < calls.size()) {
				return 0;
			} else if (!endReached && i == calls.size()) {
				return 1;
			}
			return 2;
		}
	}

	private class ViewItem {
		public ProfileSearchCell cell;
		public ImageView button;

		public ViewItem(ImageView button, ProfileSearchCell cell) {
			this.button = button;
			this.cell = cell;
		}
	}

	private class CallLogRow {
		public TLRPC.User user;
		public List<TLRPC.Message> calls;
		public int type;
	}

	@Override
	public ThemeDescription[] getThemeDescriptions() {
		ThemeDescription.ThemeDescriptionDelegate cellDelegate = new ThemeDescription.ThemeDescriptionDelegate() {
			@Override
			public void didSetColor() {
				if (listView != null) {
					int count = listView.getChildCount();
					for (int a = 0; a < count; a++) {
						View child = listView.getChildAt(a);
						if (child instanceof ProfileSearchCell) {
							((ProfileSearchCell) child).update(0);
						}
					}
				}
			}
		};

		return new ThemeDescription[]{
				new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{LocationCell.class, CustomCell.class}, null, null, null, Theme.key_windowBackgroundWhite),
				new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray),

				new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault),
				new ThemeDescription(listView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault),
				new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon),
				new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle),
				new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector),

				new ThemeDescription(listView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector),

				new ThemeDescription(listView, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider),

				new ThemeDescription(emptyView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_emptyListPlaceholder),
				new ThemeDescription(emptyView, ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_progressCircle),

				new ThemeDescription(listView, 0, new Class[]{LoadingCell.class}, new String[]{"progressBar"}, null, null, null, Theme.key_progressCircle),

				new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow),
				new ThemeDescription(listView, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4),

				new ThemeDescription(floatingButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chats_actionIcon),
				new ThemeDescription(floatingButton, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chats_actionBackground),
				new ThemeDescription(floatingButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_chats_actionPressedBackground),

				new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_verifiedCheckDrawable}, null, Theme.key_chats_verifiedCheck),
				new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_verifiedDrawable}, null, Theme.key_chats_verifiedBackground),
				new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, Theme.dialogs_offlinePaint, null, null, Theme.key_windowBackgroundWhiteGrayText3),
				new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, Theme.dialogs_onlinePaint, null, null, Theme.key_windowBackgroundWhiteBlueText3),
				new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, Theme.dialogs_namePaint, null, null, Theme.key_chats_name),
				new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, null, new Drawable[]{Theme.avatar_photoDrawable, Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text),
				new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed),
				new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange),
				new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet),
				new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundGreen),
				new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundCyan),
				new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundBlue),
				new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundPink),

				new ThemeDescription(listView, 0, new Class[]{View.class}, null, new Drawable[]{greenDrawable, greenDrawable2, Theme.chat_msgCallUpRedDrawable, Theme.chat_msgCallDownRedDrawable}, null, Theme.key_calls_callReceivedGreenIcon),
				new ThemeDescription(listView, 0, new Class[]{View.class}, null, new Drawable[]{redDrawable, Theme.chat_msgCallUpGreenDrawable, Theme.chat_msgCallDownGreenDrawable}, null, Theme.key_calls_callReceivedRedIcon),
		};
	}
}
