public class LiveChatConnection {
	protected boolean debug = false;
	protected ChannelConfig channel;
	protected UserConfig user;
	protected Credentials credentials;
    protected WebSocketConnection socket;
    protected LiveChatListener listener;
    protected boolean keepAlive = false;
    protected Thread keepAliveThread;
	
    /**
     * Create a new connection with the application credentials and the listener.
     * The listener will be notified asynchronously of messages and events.
     */
	public LiveChatConnection(Credentials credentials, LiveChatListener listener) {
		this.credentials = credentials;
		this.listener = listener;
	}
	
	/**
	 * Connection to the live chat server channel.
	 * Validate the user credentials.
	 * This call is asynchronous, any error or success with be sent as a separate message to the listener.
	 */
	public void connect(ChannelConfig channel, UserConfig user) {
		this.channel = channel;
		this.user = user;
		try {
			this.socket = new WebSocketConnection();
			this.socket.connect("ws://" + this.credentials.host + this.credentials.app
						+ "/live/chat", new WebSocketConnectionHandler() {
				@Override
				public void onOpen() {
					if (LiveChatConnection.this.user == null) {
						LiveChatConnection.this.socket.sendTextMessage("connect " + LiveChatConnection.this.channel.id + " " + LiveChatConnection.this.credentials.applicationId);
					} else {
						LiveChatConnection.this.socket.sendTextMessage(
								"connect " + LiveChatConnection.this.channel.id + " " + LiveChatConnection.this.user.user
								+ " " + LiveChatConnection.this.user.token + " " + LiveChatConnection.this.credentials.applicationId);						
					}
				}

				@Override
				public void onTextMessage(String text) {
			    	String user = "";
			    	String message = text;
			    	int index = text.indexOf(':');
			    	if (index != -1) {
			    		user = text.substring(0, index);
			    		message = text.substring(index + 2, text.length());
			    	}
					if (user.equals("Online-xml")) {
						return;
					}
					if (user.equals("Online")) {
						LiveChatConnection.this.listener.updateUsers(message);
						return;
					}
					
					if (LiveChatConnection.this.keepAlive && user.equals("Info") && text.contains("pong")) {
						return;
					}
					if (user.equals("Info")) {
						LiveChatConnection.this.listener.info(text);
						return;
					}
					if (user.equals("Error")) {
						LiveChatConnection.this.listener.error(text);
						return;
					}
					LiveChatConnection.this.listener.message(text);
				}

				@Override
				public void onClose(int code, String reason) {
					LiveChatConnection.this.listener.message("Info: Closed");
					LiveChatConnection.this.listener.closed();
				}
			});
		} catch (Exception exception) {
			throw new SDKException(exception);
		}
	}

	/**
	 * Sent a text message to the channel.
	 * This call is asynchronous, any error or success with be sent as a separate message to the listener.
	 * Note, the listener will receive its own messages.
	 */
	public void sendMessage(String message) {
		checkSocket();
		this.socket.sendTextMessage(message);
	}

	/**
	 * Accept a private request.
	 * This is also used by an operator to accept the top of the waiting queue.
	 * This can also be used by a user to chat with the channel bot.
	 * This call is asynchronous, any error or success with be sent as a separate message to the listener.
	 */
	public void accept() {
		checkSocket();
		this.socket.sendTextMessage("accept");
	}

	/**
	 * Test the connection.
	 * A pong message will be returned, this message will not be broadcast to the channel.
	 * This call is asynchronous, any error or success with be sent as a separate message to the listener.
	 */
	public void ping() {
		checkSocket();
		this.socket.sendTextMessage("ping");
	}

	/**
	 * Exit from the current private channel.
	 * This call is asynchronous, any error or success with be sent as a separate message to the listener.
	 */
	public void exit() {
		checkSocket();
		this.socket.sendTextMessage("exit");
	}

	/**
	 * Request a private chat session with a user.
	 * This call is asynchronous, any error or success with be sent as a separate message to the listener.
	 */
	public void pvt(String user) {
		checkSocket();
		this.socket.sendTextMessage("pvt: " + user);
	}

	/**
	 * Boot a user from the channel.
	 * You must be a channel administrator to boot a user.
	 * This call is asynchronous, any error or success with be sent as a separate message to the listener.
	 */
	public void boot(String user) {
		checkSocket();
		this.socket.sendTextMessage("boot: " + user);
	}

	/**
	 * Send a private message to a user.
	 * This call is asynchronous, any error or success with be sent as a separate message to the listener.
	 */
	public void whisper(String user, String message) {
		checkSocket();
		this.socket.sendTextMessage("whisper:" + user + ": " + message);
	}

	/**
	 * Disconnect from the channel.
	 */
	public void disconnect() {
    	this.keepAlive = false;
    	if (this.keepAliveThread != null) {
    		this.keepAliveThread.interrupt();
    	}
    	if (this.socket != null) {
    		this.socket.disconnect();
    	}
	}
 
    protected void runKeepAlive() {
    	this.keepAliveThread = new Thread() {
    		public void run() {
    			while (keepAlive) {
	    			sendMessage("ping");
	    			try {
	    				Thread.sleep(600000);
	    			} catch (InterruptedException exception) {
	    				return;
	    			}
    			}
    		}
    	};
    	this.keepAliveThread.start();
    }
    
    public boolean isDebug() {
		return debug;
	}

	/**
	 * Enable debugging messages (logged to System.out).
	 */
	public void setDebug(boolean debug) {
		this.debug = debug;
	}

	/**
	 * Return the current channel.
	 */
	public ChannelConfig getChannel() {
		return channel;
	}

	protected void setChannel(ChannelConfig channel) {
		this.channel = channel;
	}

	/**
	 * Return the current user.
	 */
	public UserConfig getUser() {
		return user;
	}

	protected void setUser(UserConfig user) {
		this.user = user;
	}

	/**
	 * Return the current application credentials.
	 */
	public Credentials getCredentials() {
		return credentials;
	}

	protected void setCredentials(Credentials credentials) {
		this.credentials = credentials;
	}

	public LiveChatListener getListener() {
		return listener;
	}

	public void setListener(LiveChatListener listener) {
		this.listener = listener;
	}

	/**
	 * Return if the connection will be kept alive, and not allowed to timeout due to inactivity.
	 */
	public boolean isKeepAlive() {
		return keepAlive;
	}

	/**
	 * Set if the connection should be kept alive, and not allowed to timeout due to inactivity.
	 */
	public void setKeepAlive(boolean keepAlive) {
		this.keepAlive = keepAlive;
    	if (this.keepAlive) {
    		runKeepAlive();
    	} else if (this.keepAliveThread != null) {
    		this.keepAliveThread.interrupt();
    		this.keepAliveThread = null;
    	}
    }
	
	protected void checkSocket() {
		if (this.socket == null) {
			throw new SDKException("Not connected");
		}
	}
} public interface LiveChatListener {
	/**
	 * A user message was received from the channel.
	 */
	void message(String message);
	
	/**
	 * An informational message was received from the channel.
	 * Such as a new user joined, private request, etc.
	 */	
	void info(String message);

	/**
	 * An error message was received from the channel.
	 * This could be an access error, or message failure.
	 */	
	void error(String message);
	
	/**
	 * Notification that the connection was closed.
	 */
	void closed();
	
	/**
	 * The channels users changed (user joined, left, etc.)
	 * This contains a comma separated values (CSV) list of the current channel users.
	 * It can be passed to the SDKConnection.getUsers() API to obtain the UserConfig info for the users.
	 */
	void updateUsers(String usersCSV);
} public class MainActivity extends Activity {
	public static final boolean DEBUG = false;
	public static final boolean ADULT = false;
	
	/**
	 * Enter your application ID here.
	 * You can get an application ID from any of the services websites (BOT libre, FORUMS libre, LIVE CHAT libre, Paphus Live Chat)
	 */
	 /** ** enter you app id from your user page ** */
	public static String applicationId = "";
	/**
	 * Configure your connection credentials here.
	 * Choose which service provider you wish to connect to.
	 */
	public static SDKConnection connection;
	/**
	 * To launch into a specific domain, enter the domain id here.
	 */
	public static String domainId = null;
	public static DomainConfig domain;
	public static String defaultType = "Bots";
	/**
	 * Choose your service provider using the correct credentials.
	 */
	static {
		connection = new SDKConnection(new BOTlibreCredentials(applicationId));
		//connection = new SDKConnection(new FORUMSlibreCredentials(applicationId));
		//connection = new SDKConnection(new LIVECHATlibreCredentials(applicationId));
		//connection = new SDKConnection(new PaphusCredentials(applicationId));
		if (domainId != null) {
			domain = new DomainConfig();
			domain.id = domainId;
			connection.setDomain(domain);
		}
	}
	/**
	 * If you are building a single instance app, then you can set the instance id or name here,
	 * and use this activity to launch it.
	 */
	public static String launchInstanceId = "165"; // ** enter your bot's id, i.e. "171"
	public static String launchInstanceName = "Brain Bot"; // ** nter your bot's name, i.e. "Help Bot"
	
	public static String forumId = "26662"; // ** you can also add a forum
	public static String chatroomId = "356968";  // ** or a chatroom
	
	/**
	 * If you are building a single instance app, then you can set the launchType to
	 * have this activity launch the bot, forum, or channel.
	 */
	public static LaunchType launchType = LaunchType.Bot;
	public enum LaunchType {Browse, Bot, Forum, Channel}

	public static boolean sound = true;
	public static boolean disableVideo;
	public static boolean deviceVoice;
	
	public static WebMediumConfig instance;
	public static ForumPostConfig post;
	public static UserConfig user;
	public static UserConfig viewUser;
	public static String type = "Bots";
	public static VoiceConfig voice = new VoiceConfig();
	public static String conversation;
	public static String template = "";
	public static Object[] templates;
	public static Object[] tags;
	public static Object[] categories;
	public static Object[] forumTags;
	public static Object[] forumPostTags;
	public static Object[] forumCategories;
	public static Object[] channelTags;
	public static Object[] channelCategories;
	public static boolean showImages = true;
	public static List<WebMediumConfig> instances = new ArrayList<WebMediumConfig>();
	public static List<ForumPostConfig> posts = new ArrayList<ForumPostConfig>();
	public static MainActivity current;
	public static boolean wasDelete;
	public static String[] types = new String[]{"Bots", "Forums", "Live Chat", "Domains"};
	public static String[] channelTypes = new String[]{"ChatRoom", "OneOnOne"};
	public static String[] accessModes = new String[]{"Everyone", "Users", "Members", "Administrators"};
	public static String[] learningModes = new String[]{"Disabled", "Administrators", "Users", "Everyone"};
	public static String[] correctionModes = new String[]{"Disabled", "Administrators", "Users", "Everyone"};
	public static String[] botModes = new String[]{"ListenOnly", "AnswerOnly", "AnswerAndListen"};

	Menu menu;

	public static String getFilePathFromURI(Context context, Uri uri) {
		String scheme = uri.getScheme();
		if (scheme.equals("file")) {
		    return uri.getPath(); // uri.getLastPathSegment();
		} else if (scheme.equals("content")) {
			Cursor cursor = null;
			try {
				//String selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
				//        + MediaStore.Files.FileColumns.MEDIA_TYPE_NONE;
				//String i = MediaStore.Files.FileColumns.DATA;
				String[] proj = { MediaStore.Images.Media.DATA };
				cursor = context.getContentResolver().query(uri, proj, null, null, null);
				int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
				cursor.moveToFirst();
				String path = cursor.getString(column_index);
				if (path == null) {
					return uri.getPath();
				}
				return path;
			} finally {
				if (cursor != null) {
					cursor.close();
				}
			}
	    } else {
	    	return uri.getPath();
	    }
	}

	public static String getFileNameFromPath(String path) {
		int index = path.lastIndexOf("/");
		return path.substring(index + 1, path.length());
	}

	public static String getFileTypeFromPath(String path) {
		int index = path.lastIndexOf(".");
		String ext = path.substring(index + 1, path.length());
		return MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext);
	}
	
	public static void error(String message, Exception exception, Activity activity) {
		try {
			if (DEBUG) {
				System.out.println(String.valueOf(message));
				if (exception != null) {
					exception.printStackTrace();
				}
			}
			if (message == null) {
				message = "";
			}
			if (message.contains("<html>")) {
				message = "Server Error, ensure you are connected to the Internet";
			}
			MainActivity.showMessage(message, activity);
		} catch (Throwable error) {
			error.printStackTrace();
		}
	}
	
	public static void showMessage(String message, Activity activity) {
		AlertDialog dialog = new AlertDialog.Builder(activity).create();
		dialog.setMessage(message);
		dialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", new DialogInterface.OnClickListener() {
		      public void onClick(DialogInterface dialog, int which) {}
		    });
		dialog.show();
	}
	
	public static void prompt(String message, Activity activity, EditText text, DialogInterface.OnClickListener listener) {
		AlertDialog dialog =  new AlertDialog.Builder(activity).create();
		dialog.setMessage(message);
		dialog.setView(text);
		dialog.setButton(AlertDialog.BUTTON_POSITIVE, "OK", listener);
		dialog.setButton(AlertDialog.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
	        public void onClick(DialogInterface dialog, int whichButton) {
	            // Do nothing.
	        }
	    });
		dialog.show();
	}
	
	public static void confirm(String message, Activity activity, DialogInterface.OnClickListener listener) {
		AlertDialog dialog =  new AlertDialog.Builder(activity).create();
		dialog.setMessage(message);
		dialog.setButton(AlertDialog.BUTTON_POSITIVE, "OK", listener);
		dialog.setButton(AlertDialog.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
	        public void onClick(DialogInterface dialog, int whichButton) {
	            // Do nothing.
	        }
	    });
		dialog.show();
	}
    

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
    	
		current = this;
		
		if (user == null) {
	    	SharedPreferences cookies = getPreferences(Context.MODE_PRIVATE);
	    	String user = cookies.getString("user", null);
	    	String token = cookies.getString("token", null);
	
	    	if ((user != null) && (token != null)) {
	    		UserConfig config = new UserConfig();
	    		config.user = user;
	    		config.token = token;
	    		HttpConnectAction action = new HttpConnectAction(this, config, false);
		    	action.execute();
	    	}
		}

		if ((launchType == LaunchType.Bot) || (launchType == LaunchType.Channel))  {
			setContentView(R.layout.activity_main_chat);			
		} else if (launchType == LaunchType.Forum)  {
			setContentView(R.layout.activity_main_browse);			
		} else {
			setContentView(R.layout.activity_main);
		}
		
		resetView();
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void resetView() {
		Spinner spin = (Spinner) findViewById(R.id.typeSpin);
		if (spin != null) {
			ArrayAdapter adapter = new ArrayAdapter(this,
	                android.R.layout.simple_spinner_dropdown_item, MainActivity.types);
			spin.setAdapter(adapter);
			spin.setSelection(Arrays.asList(MainActivity.types).indexOf(MainActivity.type));
			
		}
		if (domain != null) {
			setTitle(domain.name);
	        HttpGetImageAction.fetchImage(this, domain.avatar, (ImageView)findViewById(R.id.splash));			
		}
        if (MainActivity.user == null) {
        	findViewById(R.id.vewUserButton).setVisibility(View.GONE);
        	findViewById(R.id.logoutButton).setVisibility(View.GONE);
        	findViewById(R.id.loginButton).setVisibility(View.VISIBLE);
        } else {
        	findViewById(R.id.logoutButton).setVisibility(View.VISIBLE);
        	findViewById(R.id.loginButton).setVisibility(View.GONE);
        	findViewById(R.id.vewUserButton).setVisibility(View.VISIBLE);
	        HttpGetImageAction.fetchImage(this, MainActivity.user.avatar, findViewById(R.id.vewUserButton));
        }
		resetMenu();
	}
	
	@Override
	public void onResume() {
		if (user != null) {
			resetView();
			
	    	SharedPreferences.Editor cookies = getPreferences(Context.MODE_PRIVATE).edit();
	    	cookies.putString("user", MainActivity.user.user);
	    	cookies.putString("token", MainActivity.user.token);
	    	cookies.commit();
		}
		super.onResume();
	}

	
	@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.layout.menu_user, menu);
        return true;
    }
	
	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		this.menu = menu;
		resetMenu();
	    return true;
	}
	
	public void resetMenu() {
		if (this.menu == null) {
			return;
		}
        for (int index = 0; index < this.menu.size(); index++) {
    	    menu.getItem(index).setEnabled(true);        	
        }
        if (MainActivity.user == null) {
        	this.menu.findItem(R.id.menuSignOut).setEnabled(false);
        	this.menu.findItem(R.id.menuViewUser).setEnabled(false);
        	this.menu.findItem(R.id.menuEditUser).setEnabled(false);
        } else {
        	this.menu.findItem(R.id.menuSignIn).setEnabled(false);
        	this.menu.findItem(R.id.menuSignUp).setEnabled(false);
        }
	}
	
    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
         
        switch (item.getItemId())
        {  
	    case R.id.menuAbout:
	    	about();
	        return true;
	    case R.id.menuSignIn:
	    	login();
	        return true;
        case R.id.menuSignUp:
        	createUser();
            return true;
        case R.id.menuSignOut:
        	logout();
            return true;
        case R.id.menuEditUser:
        	editUser();
            return true;
        case R.id.menuViewUser:
        	viewUser();
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

	public void login(View view) {
		login();
	}

	public void logout(View view) {
		logout();
	}

	public void login() {
		Spinner spin = (Spinner) findViewById(R.id.typeSpin);
		if (spin != null) {
			type = (String)spin.getSelectedItem();
		}
		
        Intent intent = new Intent(this, LoginActivity.class);
        startActivity(intent);
    }

	public void logout() {
		Spinner spin = (Spinner) findViewById(R.id.typeSpin);
		if (spin != null) {
			type = (String)spin.getSelectedItem();
		}
		
		connection.disconnect();
        user = null;
        instance = null;
        conversation = null;
        post = null;
        posts = new ArrayList<ForumPostConfig>();
        instances = new ArrayList<WebMediumConfig>();
        domain = null;
        tags = null;
        categories= null;
        voice = null;

    	SharedPreferences.Editor editor = getPreferences(Context.MODE_PRIVATE).edit();
    	editor.putString("user", null);
    	editor.putString("token", null);
    	editor.putString("instance", null);
    	editor.commit();
    	
    	HttpGetImageAction.clearFileCache(this);
    	
        Intent intent = getIntent();
        finish();
        startActivity(intent);
    }

	public void menu(View view) {
		openOptionsMenu();
	}

	public void createUser() {
		Spinner spin = (Spinner) findViewById(R.id.typeSpin);
		if (spin != null) {
			type = (String)spin.getSelectedItem();
		}
		
        Intent intent = new Intent(this, CreateUserActivity.class);
        startActivity(intent);
	}

	public void editUser() {
		Spinner spin = (Spinner) findViewById(R.id.typeSpin);
		if (spin != null) {
			type = (String)spin.getSelectedItem();
		}
		
        Intent intent = new Intent(this, EditUserActivity.class);
        startActivity(intent);
	}

	public void viewUser(View view) {
		viewUser();
	}
	
	public void viewUser() {
		viewUser = user;
		Spinner spin = (Spinner) findViewById(R.id.typeSpin);
		if (spin != null) {
			type = (String)spin.getSelectedItem();
		}
		
        Intent intent = new Intent(this, ViewUserActivity.class);
        startActivity(intent);
	}

	public void browse(View view) {
		Spinner spin = (Spinner) findViewById(R.id.typeSpin);
		type = (String)spin.getSelectedItem();
		if (type == null) {
			type = MainActivity.defaultType;
		}
		if (type.equals("Bots")) {
	        Intent intent = new Intent(this, BrowseActivity.class);
	        startActivity(intent);			
		} else if (type.equals("Forums")) {
	        Intent intent = new Intent(this, ForumBrowseActivity.class);
	        startActivity(intent);			
		} else if (type.equals("Live Chat")) {
	        Intent intent = new Intent(this, ChannelBrowseActivity.class);
	        startActivity(intent);			
		} else if (type.equals("Domains")) {
			BrowseConfig config = new BrowseConfig();
			config.type = "Domain";
			
			HttpGetInstancesAction action = new HttpGetInstancesAction(this, config);
			action.execute();
		}
	}
	
	/**
	 * Open the details screen.
	 */
	public void about() {
		WebMediumConfig config = null;
		if (launchType == LaunchType.Bot) {
			config = new InstanceConfig();
		} else if (launchType == LaunchType.Forum) {
			config = new ForumConfig();
		} else if (launchType == LaunchType.Channel) {
			config = new ChannelConfig();
		}
        config.id = launchInstanceId;
        config.name = launchInstanceName;
		
        HttpAction action = new HttpFetchAction(this, config, false);
    	action.execute();    	
    }
	
	/**
	 * Start a chat session with the hard coded instance.
	 */
	public void launch(View view) {
		WebMediumConfig config = null;
		if (launchType == LaunchType.Bot) {
			config = new InstanceConfig();
		} else if (launchType == LaunchType.Forum) {
			config = new ForumConfig();
		} else if (launchType == LaunchType.Channel) {
			config = new ChannelConfig();
		}
        config.id = launchInstanceId;
        config.name = launchInstanceName;
		
        HttpAction action = new HttpFetchAction(this, config, true);
    	action.execute();    	
    }

	/**
	 * Launch the predefined forum.
	 */
	public void launchForum(View view) {
		WebMediumConfig config = null;
		config = new ForumConfig();
        config.id = forumId;
		
        HttpAction action = new HttpFetchAction(this, config, true);
    	action.execute();    	
    }

	/**
	 * Launch the predefined chatroom.
	 */
	public void launchChatroom(View view) {
		WebMediumConfig config = null;
		config = new ChannelConfig();
        config.id = chatroomId;
		
        HttpAction action = new HttpFetchAction(this, config, true);
    	action.execute();    	
    }
} public class ViewUserActivity extends CreateUserActivity {
	@Override
	public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_user);
        resetView();
	}
	
	@Override
	public void onResume() {
		if (MainActivity.user != null && MainActivity.user.equals(MainActivity.viewUser)) {
			MainActivity.viewUser = MainActivity.user;
		}
		resetView();
		super.onResume();
	}
	
	public void resetView() {
        UserConfig user = MainActivity.viewUser;
        if (user == null) {
        	return;
        }
        
        setTitle(user.user);
        
        TextView text = (TextView) findViewById(R.id.userText);
        text.setText(user.user);
        text = (TextView) findViewById(R.id.nameText);
        if (user.showName) {
        	text.setText(user.name);
        } else {
        	text.setVisibility(View.GONE);
            text = (TextView) findViewById(R.id.nameLabel);
        	text.setVisibility(View.GONE);
        }
        text = (TextView) findViewById(R.id.websiteText);
        if (user.website == null || user.website.length() == 0) {
        	text.setVisibility(View.GONE);
            text = (TextView) findViewById(R.id.websiteLabel);
        	text.setVisibility(View.GONE);        	
        } else {
        	text.setText(user.website);
        }
        text = (TextView) findViewById(R.id.joinedText);
        text.setText(user.joined);
        text = (TextView) findViewById(R.id.connectsText);
        text.setText(user.connects);
        text = (TextView) findViewById(R.id.lastConnectText);
        text.setText(user.lastConnect);
        text = (TextView) findViewById(R.id.botsText);
        text.setText(user.bots);
        text = (TextView) findViewById(R.id.postsText);
        text.setText(user.posts);
        text = (TextView) findViewById(R.id.messagesText);
        text.setText(user.messages);
        WebView web = (WebView) findViewById(R.id.bioText);
        web.loadDataWithBaseURL(null, user.bio, "text/html", "utf-8", null);        
        web.setWebViewClient(new WebViewClient() {
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
            	try {
            		view.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
            	} catch (Exception failed) {
            		return false;
            	}
                return true;
            }
        });
        
        HttpGetImageAction.fetchImage(this, MainActivity.viewUser.avatar, (ImageView)findViewById(R.id.imageView));
	}

	
	@Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.layout.menu_view_user, menu);
        return true;
    }
	
	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
        for (int index = 0; index < menu.size(); index++) {
    	    menu.getItem(index).setEnabled(true);        	
        }
        if (MainActivity.user == null || MainActivity.user == MainActivity.viewUser) {
    	    menu.findItem(R.id.menuFlag).setEnabled(false);
        }
        if (MainActivity.user != MainActivity.viewUser) {
    	    menu.findItem(R.id.menuChangeIcon).setEnabled(false);
    	    menu.findItem(R.id.menuEditUser).setEnabled(false);
        }
	    return true;
	}
	
    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
         
        switch (item.getItemId())
        {
	    case R.id.menuChangeIcon:
	    	changeIcon();
	        return true;
	    case R.id.menuEditUser:
	    	editUser();
	        return true;
	    case R.id.menuFlag:
	    	flag();
	        return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

	public void editUser() {
        Intent intent = new Intent(this, EditUserActivity.class);
        startActivity(intent);
	}

	public void flag() {
        if (MainActivity.user == null) {
        	MainActivity.showMessage("You must sign in to flag a user", this);
        	return;
        }
        final EditText text = new EditText(this);
        MainActivity.prompt("Enter reason for flagging the user", this, text, new DialogInterface.OnClickListener() {
	        public void onClick(DialogInterface dialog, int whichButton) {
	            WebMediumConfig instance = MainActivity.instance.credentials();
	            instance.flaggedReason = text.getText().toString();
	            if (instance.flaggedReason.trim().length() == 0) {
	            	MainActivity.error("You must enter a valid reason for flagging the user", null, ViewUserActivity.this);
	            	return;
	            }
	            
	            HttpAction action = new HttpFlagUserAction(ViewUserActivity.this, MainActivity.viewUser);
	        	action.execute();
	        }
        });
	}

	public void changeIcon() {
		Intent upload = new Intent(Intent.ACTION_GET_CONTENT);
		upload.setType("image/*");
		startActivityForResult(upload, 1);
	}

	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (resultCode != RESULT_OK) {
			return;
		}
		try {
			String file = MainActivity.getFilePathFromURI(this, data.getData());
			HttpAction action = new HttpChangeUserIconAction(this, file, MainActivity.user);
			action.execute().get();
    		if (action.getException() != null) {
    			throw action.getException();
    		}
		} catch (Exception exception) {
			MainActivity.error(exception.getMessage(), exception, this);
			return;
		}
	}

	public void menu(View view) {
		openOptionsMenu();
	}
} public abstract class HttpAction extends AsyncTask<Void, Void, String> {	
	protected Activity activity;
	protected Exception exception;

	public HttpAction(Activity activity) {
		this.activity = activity;
	}
		
	public Exception getException() {
		return exception;
	}

	public void setException(Exception exception) {
		this.exception = exception;
	}
} public class HttpCreateChannelFileAttachmentAction extends HttpUIAction {

	MediaConfig config;
	String file;
	
	public HttpCreateChannelFileAttachmentAction(Activity activity, String file, MediaConfig config) {
		super(activity);
		this.config = config;
		this.file = file;
	}

	@Override
	protected String doInBackground(Void... params) {
		try {
		this.config = MainActivity.connection.createChannelFileAttachment(this.file, this.config);
		} catch (Exception exception) {
			this.exception = exception;
		}
		return "";
	}

	@Override
	public void onPostExecute(String xml) {
		super.onPostExecute(xml);
		if (this.exception != null) {
			return;
		}
		((LiveChatActivity)this.activity).sendFile(config);
    }
} public class HttpCreateChannelImageAttachmentAction extends HttpCreateChannelFileAttachmentAction {
	
	public HttpCreateChannelImageAttachmentAction(Activity activity, String file, MediaConfig config) {
		super(activity, file, config);
	}

	@Override
	protected String doInBackground(Void... params) {
		try {
		this.config = MainActivity.connection.createChannelImageAttachment(this.file, this.config);
		} catch (Exception exception) {
			this.exception = exception;
		}
		return "";
	}
} public class HttpGetImageAction extends HttpAction {
	public static int MAX_HEIGHT = 300;
	public static int MAX_WIDTH = 300;
	public static int MAX_FILES = 100;
	
	public static volatile boolean downloading;
	
	static File cacheDir;	
	static Map<String, SoftReference<Bitmap>> imageCache = new Hashtable<String, SoftReference<Bitmap>>();
	
	String image;
	Bitmap bmp;
	View view;
	
	public static void clearFileCache(Context context) {
		try {
			File[] files = getFileCacheDir(context).listFiles();
	        if (files == null) {
	            return;
	        }
	        for (File file : files) {
	        	boolean success = false;
	        	if (file.isDirectory()) {
	        		File[] nested = file.listFiles();
	    	        for (File nestedFile : nested) {
	    	        	if (!nestedFile.isDirectory()) {
	    	        		success = nestedFile.delete();
	    	        	}
	    	        }
	        	} else {
	        		success = file.delete();
	        	}
	        }
		} catch (Exception failed) {
			Log.wtf(failed.toString(), failed);
		}
    }
	
    public static File getFileCacheDir(Context context) {
    	if (cacheDir == null) {
    		try {
		        //if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
		        //    cacheDir = new File(android.os.Environment.getExternalStorageDirectory().toString() + "/botlibre");
		        //} else {
		            cacheDir = context.getCacheDir();
		        //}
		        if (!cacheDir.exists()) {
		            cacheDir.mkdirs();
		        }
    		} catch (Exception failed) {
    			failed.printStackTrace();
    			return null;
    		}
    	}
    	return cacheDir;
    }
    
    public static File getFile(String filename, Context context) {
    	File dir = getFileCacheDir(context);
    	if (dir == null) {
    		return null;
    	}
    	
    	File file = new File(dir.getAbsolutePath() + "/" + filename);
    	dir = new File(file.getParent());
    	if (!dir.exists()) {
    		dir.mkdir();
    	} else {
	        File[] files = dir.listFiles();
	    	if (files.length > MAX_FILES) {
    	        for (File nestedFile : files) {
    	        	if (!nestedFile.isDirectory()) {
    	        		nestedFile.delete();
    	        	}
    	        }	    		
	    	}
    	}
    	return file;
    }
	
	public static void fetchImage(Activity activity, String image, View view) {
		if (image == null) {
			return;
		}
		SoftReference<Bitmap> ref = imageCache.get(image);
		if (ref != null) {
			Bitmap bmp = ref.get();
			if (bmp != null) {
				if (view instanceof ImageView) {
					((ImageView)view).setImageBitmap(bmp);
				} else if (view instanceof Button) {
					((Button)view).setBackgroundDrawable(new BitmapDrawable(view.getResources(), bmp));					
				}
		        return;
			}
		}
        HttpGetImageAction action = new HttpGetImageAction(activity, image, view);
    	try {
    		action.execute().get();
    		action.postExecute();
    		if (action.getException() != null) {
    			throw action.getException();
    		}
    	} catch (Exception exception) {
    		if (MainActivity.DEBUG) {
    			exception.printStackTrace();
    		}
    		return;
    	}
	}
	
	public HttpGetImageAction(Activity activity) {
		super(activity);
	}
	
	public HttpGetImageAction(Activity activity, String image, View view) {
		super(activity);
		this.image = image;
		this.view = view;
	}

	@Override
	protected String doInBackground(Void... params) {
        try {
	        URL url = MainActivity.connection.fetchImage(this.image);
		    
		    /*BitmapFactory.Options options = new BitmapFactory.Options();
		    options.inJustDecodeBounds = true;
		    long start = System.currentTimeMillis();
		    InputStream stream = url.openConnection().getInputStream();
		    BitmapFactory.decodeStream(stream, null, options);
		    stream.close();
		    System.out.println("decodeStream1:" + (System.currentTimeMillis() - start));

	        int height = options.outHeight;
	        int width = options.outWidth;
	        options.inPreferredConfig = Bitmap.Config.RGB_565;
	        int inSampleSize = 1;

	        if (height > MAX_HEIGHT) {
	            inSampleSize = Math.round((float)height / (float)MAX_HEIGHT);
	        }

	        int expectedWidth = width / inSampleSize;

	        if (expectedWidth > MAX_WIDTH) {
	            inSampleSize = Math.round((float)width / (float)MAX_WIDTH);
	        }

		    options.inSampleSize = inSampleSize;
		    options.inJustDecodeBounds = false;

		    start = System.currentTimeMillis();
		    stream = url.openConnection().getInputStream();
		    BitmapFactory.decodeStream(stream, null, options).recycle();
		    stream.close();
		    System.out.println("decodeStream2:" + (System.currentTimeMillis() - start));

		    start = System.currentTimeMillis();
		    stream = url.openConnection().getInputStream();
		    BitmapFactory.decodeStream(stream).recycle();
		    stream.close();
		    System.out.println("decodeStream-full:" + (System.currentTimeMillis() - start));*/

		    File file = getFile(this.image, this.activity);
		    if (!file.exists()) {
		    	downloading = true;
		    	file.createNewFile();
		    	FileOutputStream outputStream = new FileOutputStream(file);
			    InputStream stream = url.openConnection().getInputStream();
		    	byte[] bytes= new byte[1024];
		    	int count = 0;
	            while (count != -1) {
	            	count = stream.read(bytes, 0, 1024);
		            if (count == -1) {
		            	break;
		            }
		            outputStream.write(bytes, 0, count);
	            }
	            stream.close();
	            outputStream.close();
		    	downloading = false;
		    }

		    BitmapFactory.Options options = new BitmapFactory.Options();
		    options.inJustDecodeBounds = true;
		    InputStream stream = new FileInputStream(file);
		    BitmapFactory.decodeStream(stream, null, options);
		    stream.close();

	        int height = options.outHeight;
	        int width = options.outWidth;
	        options.inPreferredConfig = Bitmap.Config.RGB_565;
	        int inSampleSize = 1;
	        if (height > MAX_HEIGHT) {
	            inSampleSize = Math.round((float)height / (float)MAX_HEIGHT);
	        }
	        int expectedWidth = width / inSampleSize;
	        if (expectedWidth > MAX_WIDTH) {
	            inSampleSize = Math.round((float)width / (float)MAX_WIDTH);
	        }
		    options.inSampleSize = inSampleSize;
		    options.inJustDecodeBounds = false;

		    stream = new FileInputStream(file);
		    this.bmp = BitmapFactory.decodeStream(stream, null, options);
		    stream.close();
			    
	        imageCache.put(this.image, new SoftReference<Bitmap>(this.bmp));
	        return "";
        } catch (Exception exception) {
    		if (MainActivity.DEBUG) {
    			exception.printStackTrace();
    		}
        }
        return null;
	}

	protected void postExecute() {
		if (view instanceof ImageView) {
			((ImageView)view).setImageBitmap(bmp);
		} else if (view instanceof Button) {
			((Button)view).setBackgroundDrawable(new BitmapDrawable(view.getResources(), bmp));					
		}
	}
} public class HttpGetLiveChatUsersAction extends HttpAction {
	String csv;
	List<UserConfig> users;

	public HttpGetLiveChatUsersAction(Activity activity, String csv) {
		super(activity);
		this.csv = csv;
	}

	@Override
	protected String doInBackground(Void... params) {
		try {
		this.users = MainActivity.connection.getUsers(this.csv);
		} catch (Exception exception) {
			this.exception = exception;
		}
		return "";
	}

	@Override
	protected void onPostExecute(String xml) {
		super.onPostExecute(xml);
		if (this.exception != null) {
			return;
		}
		try {
			((LiveChatActivity)this.activity).setUsers(this.users);
	
		} catch (Exception error) {
			this.exception = error;
			return;			
		}
	}
	
} public class ChannelConfig extends WebMediumConfig {
	public String type;
	public String messages;
	public String usersOnline;
	public String adminsOnline;
	
	public String getType() {
		return "channel";
	}

	@Override
	public String stats() {
		return this.usersOnline + " users online, " + this.adminsOnline + " admins";
	}
	
	public WebMediumConfig credentials() {
		ChannelConfig config = new ChannelConfig();
		config.id = this.id;
		return config;
	}
	
	public String toXML() {
		StringWriter writer = new StringWriter();
		writer.write("<channel");
		if (this.type != null && !this.type.equals("")) {
			writer.write(" type=\"" + this.type + "\"");
		}
		writeXML(writer);
		writer.write("</channel>");
		return writer.toString();
	}
	
	public void parseXML(Element element) {
		super.parseXML(element);
		this.type = element.getAttribute("type");
		this.messages = element.getAttribute("messages");
		this.usersOnline = element.getAttribute("usersOnline");
		this.adminsOnline = element.getAttribute("adminsOnline");
	}
} public class MediaConfig extends Config {
	public long id;
	public String name;
	public String type;
	public String file;
	public String key;
	
	public void parseXML(Element element) {
		super.parseXML(element);
		
		this.id = Long.valueOf(element.getAttribute("id"));
		this.name = element.getAttribute("name");
		this.type = element.getAttribute("type");
		this.file = element.getAttribute("file");
		this.key = element.getAttribute("key");
	}

	
	public String toXML() {
		StringWriter writer = new StringWriter();
		writer.write("<media");
		writeCredentials(writer);

		if (this.id != 0) {
			writer.write(" id=\"" + this.id + "\"");
		}
		if (this.name != null) {
			writer.write(" name=\"" + this.name + "\"");
		}
		if (this.type != null) {
			writer.write(" type=\"" + this.type + "\"");
		}
		if (this.file != null) {
			writer.write(" file=\"" + this.file + "\"");
		}
		if (this.key != null) {
			writer.write(" key=\"" + this.key + "\"");
		}
		
		writer.write("/>");
		return writer.toString();
	}
} public class UserConfig extends Config {
	public String password;
	public String newPassword;
	public String hint;
	public String name;
	public boolean showName;
	public String email;
	public String website;
	public String bio;
	public boolean over18;
	public String avatar;
	
	public String connects;
	public String bots;
	public String posts;
	public String messages;
	public String forums;
	public String scripts;
	public String avatars;
	public String domains;
	public String channels;
	
	public String joined;
	public String lastConnect;

	
	public void addCredentials(SDKConnection connection) {
		this.application = connection.getCredentials().getApplicationId();
		if (connection.getDomain() != null) {
			this.domain = connection.getDomain().id;
		}
	}

	public void parseXML(Element element) {
		this.user = element.getAttribute("user");
		this.name = element.getAttribute("name");
		this.showName = Boolean.valueOf(element.getAttribute("showName"));
		this.token = element.getAttribute("token");
		this.email = element.getAttribute("email");
		this.hint = element.getAttribute("hint");
		this.website = element.getAttribute("website");
		this.connects = element.getAttribute("connects");
		this.bots = element.getAttribute("bots");
		this.posts = element.getAttribute("posts");
		this.messages = element.getAttribute("messages");
		this.avatars = element.getAttribute("avatars");
		this.scripts = element.getAttribute("scripts");
		this.domains = element.getAttribute("domains");
		this.joined = element.getAttribute("joined");
		this.lastConnect = element.getAttribute("lastConnect");
		
		Node node = element.getElementsByTagName("bio").item(0);
		if (node != null) {
			this.bio = node.getTextContent();
		}
		node = element.getElementsByTagName("avatar").item(0);
		if (node != null) {
			this.avatar = node.getTextContent();
		}
	}
	
	public String toXML() {
		StringWriter writer = new StringWriter();
		writer.write("<user");
		writeCredentials(writer);
		if (this.password != null) {
			writer.write(" password=\"" + this.password + "\"");
		}
		if (this.newPassword != null) {
			writer.write(" newPassword=\"" + this.newPassword + "\"");
		}
		if (this.hint != null) {
			writer.write(" hint=\"" + this.hint + "\"");
		}
		if (this.name != null) {
			writer.write(" name=\"" + this.name + "\"");
		}
		if (this.showName) {
			writer.write(" showName=\"" + this.showName + "\"");
		}
		if (this.email != null) {
			writer.write(" email=\"" + this.email + "\"");
		}
		if (this.website != null) {
			writer.write(" website=\"" + this.website + "\"");
		}
		if (this.over18) {
			writer.write(" over18=\"" + this.over18 + "\"");
		}
		writer.write(">");
		
		if (this.bio != null) {
			writer.write("<bio>");
			writer.write(this.bio);
			writer.write("</bio>");
		}
		writer.write("</user>");
		return writer.toString();
	}
		
} public class VoiceConfig extends Config {
	
	public String language;	
	public String pitch;
	public String speechRate;
	
	public void parseXML(Element element) {
		super.parseXML(element);
		
		this.language = element.getAttribute("language");
		this.pitch = element.getAttribute("pitch");
		this.speechRate = element.getAttribute("speechRate");
	}

	
	public String toXML() {
		StringWriter writer = new StringWriter();
		writer.write("<voice");
		writeCredentials(writer);

		if (this.language != null) {
			writer.write(" language=\"" + this.language + "\"");
		}
		if (this.pitch != null) {
			writer.write(" pitch=\"" + this.pitch + "\"");
		}
		if (this.speechRate != null) {
			writer.write(" speechRate=\"" + this.speechRate + "\"");
		}
		
		writer.write("/>");
		return writer.toString();
	}
} public abstract class WebMediumConfig extends Config {
	public String id;
	public String name;
	public boolean isAdmin;
	public boolean isAdult;
	public boolean isPrivate;
	public boolean isHidden;
	public String accessMode;
	public boolean isFlagged;
	public boolean isExternal;
	public boolean isPaphus;
	public boolean showAds = true;
	public String description;
	public String details;
	public String disclaimer;
	public String website;
	public String tags;
	public String categories;
	public String flaggedReason;
	public String creator;
	public String creationDate;
	public String lastConnectedUser;
	public String license;
	public String avatar;
	public String connects;
	public String dailyConnects;
	public String weeklyConnects;
	public String monthlyConnects;
	
	public abstract String toXML();
	
	public abstract String getType();
	
	public abstract WebMediumConfig credentials();
	
	public String stats() {
		return "";
	}
	
	public boolean equals(Object object) {
		if (object instanceof WebMediumConfig) {
			if (this.id == null) {
				return super.equals(object);
			}
			return this.id.equals(((WebMediumConfig)object).id);
		}
		return false;
	}
	
	public long getToken() {
		long token = 0;
		if ((this.token != null) && (this.token.equals(""))) {
			token = Long.valueOf(this.token);
		}
		return token;
	}

	public void writeXML(StringWriter writer) {
		writeCredentials(writer);
		if (this.id != null) {
			writer.write(" id=\"" + this.id + "\"");
		}
		if (this.name != null) {
			writer.write(" name=\"" + this.name + "\"");
		}
		if (this.isPrivate) {
			writer.write(" isPrivate=\"true\"");
		}
		if (this.isHidden) {
			writer.write(" isHidden=\"true\"");
		}
		if (this.accessMode != null && !this.accessMode.equals("")) {
			writer.write(" accessMode=\"" + this.accessMode + "\"");
		}
		if (this.isAdult) {
			writer.write(" isAdult=\"true\"");
		}
		if (this.isFlagged) {
			writer.write(" isFlagged=\"true\"");
		}
		if (this.isExternal) {
			writer.write(" isExternal=\"true\"");
		}
		if (this.showAds) {
			writer.write(" showAds=\"true\"");
		}
		writer.write(">");
		if (this.description != null) {
			writer.write("<description>");
			writer.write(this.description);
			writer.write("</description>");
		}
		if (this.details != null) {
			writer.write("<details>");
			writer.write(this.details);
			writer.write("</details>");
		}
		if (this.disclaimer != null) {
			writer.write("<disclaimer>");
			writer.write(this.disclaimer);
			writer.write("</disclaimer>");
		}
		if (this.categories != null) {
			writer.write("<categories>");
			writer.write(this.categories);
			writer.write("</categories>");
		}
		if (this.tags != null) {
			writer.write("<tags>");
			writer.write(this.tags);
			writer.write("</tags>");
		}
		if (this.license != null) {
			writer.write("<license>");
			writer.write(this.license);
			writer.write("</license>");
		}
		if (this.website != null) {
			writer.write("<website>");
			writer.write(this.website);
			writer.write("</website>");
		}
		if (this.flaggedReason != null) {
			writer.write("<flaggedReason>");
			writer.write(this.flaggedReason);
			writer.write("</flaggedReason>");
		}
	}
	
	public void parseXML(Element element) {
		this.id = element.getAttribute("id");
		this.name = element.getAttribute("name");
		this.creationDate = element.getAttribute("creationDate");
		this.isPrivate = Boolean.valueOf(element.getAttribute("isPrivate"));
		this.isHidden = Boolean.valueOf(element.getAttribute("isHidden"));
		this.accessMode = element.getAttribute("accessMode");
		this.isAdmin = Boolean.valueOf(element.getAttribute("isAdmin"));
		this.isAdult = Boolean.valueOf(element.getAttribute("isAdult"));
		this.isFlagged = Boolean.valueOf(element.getAttribute("isFlagged"));
		this.isExternal = Boolean.valueOf(element.getAttribute("isExternal"));
		this.creator = element.getAttribute("creator");
		this.creationDate = element.getAttribute("creationDate");
		this.connects = element.getAttribute("connects");
		this.dailyConnects = element.getAttribute("dailyConnects");
		this.weeklyConnects = element.getAttribute("weeklyConnects");
		this.showAds = Boolean.valueOf(element.getAttribute("showAds"));
		this.monthlyConnects = element.getAttribute("monthlyConnects");
		
		Node node = element.getElementsByTagName("description").item(0);
		if (node != null) {
			this.description = node.getTextContent();
		}
		node = element.getElementsByTagName("details").item(0);
		if (node != null) {
			this.details = node.getTextContent();
		}
		node = element.getElementsByTagName("disclaimer").item(0);
		if (node != null) {
			this.disclaimer = node.getTextContent();
		}
		node = element.getElementsByTagName("categories").item(0);
		if (node != null) {
			this.categories = node.getTextContent();
		}
		node = element.getElementsByTagName("tags").item(0);
		if (node != null) {
			this.tags = node.getTextContent();
		}
		node = element.getElementsByTagName("flaggedReason").item(0);
		if (node != null) {
			this.flaggedReason = node.getTextContent();
		}
		node = element.getElementsByTagName("lastConnectedUser").item(0);
		if (node != null) {
			this.lastConnectedUser = node.getTextContent();
		}
		node = element.getElementsByTagName("license").item(0);
		if (node != null) {
			this.license = node.getTextContent();
		}
		node = element.getElementsByTagName("avatar").item(0);
		if (node != null) {
			this.avatar = node.getTextContent();
		}
	}
} public class Utils {
	
	public static Pattern httpRegex = Pattern.compile("\\b(?:https?|ftp|file):\\/\\/[a-z0-9-+&@#\\/%?=~_|!:,.;]*[a-z0-9-+&@#\\/%=~_|]", Pattern.CASE_INSENSITIVE);
	public static Pattern wwwRegex = Pattern.compile("((www\\.)[^\\s]+)", Pattern.CASE_INSENSITIVE);
	public static Pattern emailRegex = Pattern.compile("(([a-zA-Z0-9_\\-\\.]+)@[a-zA-Z_]+?(?:\\.[a-zA-Z]{2,6}))+", Pattern.CASE_INSENSITIVE);
	
	/**
	 * Replace links with HTML links.
	 * Includes http, www, images, video, audio, email address.
	 */
	public static String linkHTML(String text) {
		if (text == null || text.length() == 0) {
			return "";
		}
		boolean http = text.indexOf("http") != -1;
		boolean www = text.indexOf("www.") != -1;
		boolean email = text.indexOf("@") != -1;
		if (!http && !www && !email) {
			return text;
		}
		if (text.indexOf("<") != -1 && text.indexOf(">") != -1) {
			return text;
		}
		if (http) {
			Matcher matcher = httpRegex.matcher(text);
			StringBuffer sb = new StringBuffer();
			while (matcher.find()) {
				String url = matcher.group();
		    	if (url.indexOf(".png") != -1 || url.indexOf(".jpg") != -1 || url.indexOf(".jpeg") != -1 || url.indexOf(".gif") != -1) {
		    		url = "<a href='" + url + "' target='_blank'><img src='" + url + "' height='50'></a>";
		    	} else if (url.indexOf(".mp4") != -1 || url.indexOf(".webm") != -1 || url.indexOf(".ogg") != -1) {
		    		url = "<a href='" + url + "' target='_blank'><video src='" + url + "' height='50'></a>";
		    	} else if (url.indexOf(".wav") != -1 || url.indexOf(".mp3") != -1) {
		    		url = "<a href='" + url + "' target='_blank'><audio src='" + url + "' controls>audio</a>";
		    	} else {
		    		url = "<a href='" + url + "' target='_blank'>" + url + "</a>";
		    	}
				matcher.appendReplacement(sb, url);
			}
			matcher.appendTail(sb);
			text = sb.toString();
		} else if (www) {
			Matcher matcher = wwwRegex.matcher(text);
			StringBuffer sb = new StringBuffer();
			while (matcher.find()) {
				String url = matcher.group();
				matcher.appendReplacement(sb, "<a href='http://" + url + "' target='_blank'>" + url + "</a>");
			}
			matcher.appendTail(sb);
			text = sb.toString();
		}
		
		if (email) {
			Matcher matcher = emailRegex.matcher(text);
			StringBuffer sb = new StringBuffer();
			while (matcher.find()) {
				String address = matcher.group();
				matcher.appendReplacement(sb, "<a href='mailto://" + address + "' target='_blank'>" + address + "</a>");
			}
			matcher.appendTail(sb);
			text = sb.toString();
		}
		return text;
	}
	
	/**
	 * Strip the HTML tags from the text.
	 */
	public static String stripTags(String html) {
		if (html == null) {
			return "";
		}
		if ((html.indexOf('<') == -1) || (html.indexOf('>') == -1)) {
			return html;
		}		
		StringWriter writer = new StringWriter();
		TextStream stream = new TextStream(html);
		while (!stream.atEnd()) {
			String text = stream.upTo('<');
			writer.write(text);
			int position = stream.getPosition();
			stream.skip();
			String word = stream.nextWord();
			if (word != null) {
				if (word.equals("p")) {
					writer.write("\n\n");
				} else if (word.equals("br")) {
					writer.write("\n");
				} else if (word.equals("div")) {
					writer.write("\n");
				}
				stream.skipTo('>');
				if (stream.atEnd()) {
					stream.setPosition(position);
					writer.write(stream.upToEnd());
				} else {
					stream.skip();
				}
			}
		}
		return writer.toString();
	}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
import com.paphus.sdk.LiveChatConnection;
import com.paphus.sdk.LiveChatListener;
import com.paphus.sdk.activity.MainActivity;
import com.paphus.sdk.activity.R;
import com.paphus.sdk.activity.ViewUserActivity;
import com.paphus.sdk.activity.actions.HttpAction;
import com.paphus.sdk.activity.actions.HttpCreateChannelFileAttachmentAction;
import com.paphus.sdk.activity.actions.HttpCreateChannelImageAttachmentAction;
import com.paphus.sdk.activity.actions.HttpGetImageAction;
import com.paphus.sdk.activity.actions.HttpGetLiveChatUsersAction;
import com.paphus.sdk.config.ChannelConfig;
import com.paphus.sdk.config.MediaConfig;
import com.paphus.sdk.config.UserConfig;
import com.paphus.sdk.config.VoiceConfig;
import com.paphus.sdk.config.WebMediumConfig;
import com.paphus.sdk.util.Utils;
                intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "en-US");
 
                try {
                    startActivityForResult(intent, RESULT_SPEECH);
                    textView.setText("");
                } catch (ActivityNotFoundException a) {
                    Toast t = Toast.makeText(getApplicationContext(),
                            "Your device doesn't support Speech to Text",
                            Toast.LENGTH_SHORT);
                    t.show();
                }
            }
        });

		final ListView list = (ListView) findViewById(R.id.usersList);
		list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
			@Override
		   public void onItemClick(AdapterView<?> adapter, View view, int position, long arg) {
				UserConfig userConfig = (UserConfig)list.getItemAtPosition(position);
				if (userConfig != null) {
					setText(userConfig.user + ": ");
				}
			}
		});
		
		GestureDetector.SimpleOnGestureListener listener = new GestureDetector.SimpleOnGestureListener() {
			@Override
			public boolean onDoubleTapEvent(MotionEvent event) {
				if (event.getAction() == MotionEvent.ACTION_UP) {
					View imageLayout = findViewById(R.id.usersList);
					if (imageLayout.getVisibility() == View.VISIBLE) {
						imageLayout.setVisibility(View.GONE);
					} else {
						imageLayout.setVisibility(View.VISIBLE);					
					}
					return true;
				}
				return false;
			}
		};
		final GestureDetector detector = new GestureDetector(this, listener);
		findViewById(R.id.logText).setOnTouchListener(new View.OnTouchListener() {			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				return detector.onTouchEvent(event);
			}
		});
		
        HttpGetImageAction.fetchImage(this, MainActivity.instance.avatar, (ImageView)findViewById(R.id.imageView));

		try {
			this.connection = new LiveChatConnection(MainActivity.connection.getCredentials(),
					new LiveChatListener() {						
						@Override
						public void message(String message) {
							response(message);							
						}
						
						@Override
						public void info(String message) {
							response(message);							
						}
						
						@Override
						public void error(String message) {
							response(message);							
						}
					    
					    public void updateUsers(String csv) {
							HttpAction action = new HttpGetLiveChatUsersAction(LiveChatActivity.this, csv);
							action.execute();
							return;
					    }
						
						@Override
						public void closed() {	}		
					});
			this.connection.connect((ChannelConfig)MainActivity.instance, MainActivity.user);
		} catch (Exception exception) {
			MainActivity.error(exception.getMessage(), exception, this);
		}
	}
	
	@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        
		if (this.childActivity.equals("")) {
	        if (requestCode == RESULT_SPEECH) {
	            if (resultCode == RESULT_OK && null != data) {
	 
	                ArrayList<String> text = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
	                if (text != null) {
	                	textView.setText(text.get(0));
	                	submitChat();
	                }
	            }
	            return;
	        }
	        return;
		}
        
	    if (resultCode != RESULT_OK) {
			return;
		}
	    if (data == null || data.getData() == null) {
			this.childActivity = "";
			return;
		}
	    
		try {
			String file = MainActivity.getFilePathFromURI(this, data.getData());
			MediaConfig config = new MediaConfig();
			config.name = MainActivity.getFileNameFromPath(file);
			config.type = MainActivity.getFileTypeFromPath(file);
			config.instance = MainActivity.instance.id;
			if (this.childActivity.equals("sendImage")) {
				HttpAction action = new HttpCreateChannelImageAttachmentAction(this, file, config);
				action.execute().get();
			} else {
				HttpAction action = new HttpCreateChannelFileAttachmentAction(this, file, config);