package edu.washington.cs.oneswarm.ui.gwt.client.newui.friends.wizard;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import edu.washington.cs.oneswarm.ui.gwt.client.OneSwarmGWT;
import edu.washington.cs.oneswarm.ui.gwt.client.OneSwarmRPCClient;
import edu.washington.cs.oneswarm.ui.gwt.client.i18n.OSMessages;
import edu.washington.cs.oneswarm.ui.gwt.client.newui.HelpButton;
import edu.washington.cs.oneswarm.ui.gwt.client.newui.OneSwarmCss;
import edu.washington.cs.oneswarm.ui.gwt.client.newui.creation.CreateSwarmDialogBox;
import edu.washington.cs.oneswarm.ui.gwt.client.newui.friends.FriendPropertiesPanel;
import edu.washington.cs.oneswarm.ui.gwt.rpc.FriendInfoLite;
import edu.washington.cs.oneswarm.ui.gwt.rpc.OneSwarmUIServiceAsync;
public class MultipleManualFriendAddPanel extends VerticalPanel implements ClickHandler {
private static OSMessages msg = OneSwarmGWT.msg;
public static final int WIDTH = 530;
private String mPasted;
private HTML contextLabel;
private TextBox nickBox;
private Button nextButton;
private Button skipButton;
protected Map<Integer, String> mScannedKeys;
protected Integer[] mScannedKeysByID;
private boolean generateName = true;
private TextArea bigArea;
private int currKeyIndex = 0;
private FriendsImportCallback callback;
private Hyperlink moreUpLink;
private Hyperlink moreDownLink;
private int currAheadContext;
private int currBehindContext;
private CheckBox limitedFriendBox;
private HTML headerLabel;
public MultipleManualFriendAddPanel(FriendsImportCallback _fwcallback) {
this.callback = _fwcallback;
Label selectLabel = new Label(msg.add_friends_manual_multi_instructions());
selectLabel.addStyleName(FriendsImportWizard.CSS_DIALOG_HEADER);
selectLabel.setWidth(WIDTH + "px");
add(selectLabel);
bigArea = new TextArea();
bigArea.setVisibleLines(20);
bigArea.setWidth(WIDTH - 8 + "px");
// bigArea.setHeight("400px");
add(bigArea);
final Button scanButton = new Button(msg.add_friends_manual_multi_button_scan());
HorizontalPanel hp = new HorizontalPanel();
hp.add(scanButton);
hp.setSpacing(3);
add(hp);
this.setCellHorizontalAlignment(hp, HorizontalPanel.ALIGN_RIGHT);
scanButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
scanButton.setEnabled(false);
OneSwarmRPCClient.getService().scanXMLForFriends(OneSwarmRPCClient.getSessionID(),
bigArea.getText(), new AsyncCallback<FriendInfoLite[]>() {
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
public void onSuccess(FriendInfoLite[] result) {
if (result == null) {
parseAsText();
} else {
callback.connectSuccesful(result, true);
}
}
});
}
});
}
protected void parseAsText() {
mScannedKeys = look_for_keys(bigArea.getText());
if (mScannedKeys.size() == 0) {
Window.alert(msg.add_friends_manual_multi_alert_none_found());
return;
}
mScannedKeysByID = mScannedKeys.keySet().toArray(new Integer[0]);
Arrays.sort(mScannedKeysByID);
redisplayWithKeys();
}
protected void redisplayWithKeys() {
this.clear();
skipButton = new Button(msg.add_friends_manual_multi_button_skip());
nextButton = new Button(mScannedKeys.size() > 1 ? msg.button_next() : msg.button_done());
nickBox = new TextBox();
limitedFriendBox = new CheckBox(msg.friend_properties_limited());
skipButton.addClickHandler(this);
nextButton.addClickHandler(this);
skipButton.addStyleName(OneSwarmCss.SMALL_BUTTON);
nextButton.addStyleName(OneSwarmCss.SMALL_BUTTON);
HorizontalPanel header = new HorizontalPanel();
header.setWidth(WIDTH + "px");
// header.setSpacing(3);
Label label = new HTML(
msg.add_friends_manual_multi_key_counter_HTML(1, mScannedKeys.size()));
headerLabel = (HTML) label;
header.add(label);
header.setCellVerticalAlignment(label, ALIGN_MIDDLE);
HorizontalPanel bb = new HorizontalPanel();
bb.add(skipButton);
bb.add(nextButton);
header.addStyleName(CreateSwarmDialogBox.CSS_DIALOG_HEADER);
HorizontalPanel nickPanel = new HorizontalPanel();
nickPanel.setSpacing(3);
label = new Label(msg.friend_properties_nickname_label());
nickPanel.add(label);
nickPanel.setCellVerticalAlignment(label, ALIGN_MIDDLE);
nickPanel.add(nickBox);
HorizontalPanel limitedPanel = new HorizontalPanel();
limitedPanel.setSpacing(3);
limitedFriendBox.setValue(false);
limitedPanel.add(limitedFriendBox);
limitedPanel.setCellVerticalAlignment(limitedFriendBox, HorizontalPanel.ALIGN_MIDDLE);
HelpButton helpButton = new HelpButton(FriendPropertiesPanel.LIMITED_FRIEND);
limitedPanel.add(helpButton);
limitedPanel.setCellVerticalAlignment(helpButton, HorizontalPanel.ALIGN_MIDDLE);
limitedPanel.setCellHorizontalAlignment(helpButton, HorizontalPanel.ALIGN_RIGHT);
// limitedPanel.setWidth("100%");
nickPanel.add(limitedPanel);
// nickPanel.setWidth("100%");
nickPanel.add(bb);
nickPanel.setCellHorizontalAlignment(bb, ALIGN_RIGHT);
nickPanel.setCellVerticalAlignment(bb, ALIGN_MIDDLE);
moreUpLink = new Hyperlink(msg.add_friends_manual_multi_show_more(), "more");
moreDownLink = new Hyperlink(msg.add_friends_manual_multi_show_more(), "more");
moreUpLink.addClickHandler(this);
moreDownLink.addClickHandler(this);
contextLabel = new HTML("");
contextLabel.setWidth(WIDTH + "px");
contextLabel.setWordWrap(true);
DOM.setStyleAttribute(contextLabel.getElement(), "word-wrap", "break-word");
this.add(header);
this.add(nickPanel);
this.add(moreUpLink);
this.add(contextLabel);
this.add(moreDownLink);
currBehindContext = currAheadContext = 128;
selectKey(currKeyIndex);
}
protected void selectKey(int index) {
headerLabel.setHTML(msg.add_friends_manual_multi_key_counter_HTML(index + 1,
mScannedKeys.size()));
int previousContext = this.currBehindContext;
int nextContext = this.currAheadContext;
Integer offset = mScannedKeysByID[index];
String pasted = mPasted;
int len = 0;
for (int i = offset, valid = 0; valid < 216 && i < pasted.length(); i++, len++) {
if (pasted.charAt(i) == '\n') {
continue;
}
valid++;
}
pasted = pasted.substring(0, offset) + "<b>" + pasted.substring(offset, offset + len)
+ "</b>" + pasted.substring(offset + len, pasted.length());
int begin = Math.max(offset - previousContext, 0);
int end = Math.min(offset + len + nextContext, pasted.length());
String context = pasted.substring(begin, end);
context = context.replaceAll("\n", "<br>");
contextLabel.setHTML(context);
String keyStr = mScannedKeys.get(offset);
if (generateName) {
nickBox.setText("Friend_" + keyStr.hashCode());
generateName = false;
}
}
public Map<Integer, String> look_for_keys(String str) {
Map<Integer, String> indices = new HashMap<Integer, String>();
str = str.replaceAll("<", "");
str = str.replaceAll(">", "");
mPasted = str;
int curr = 0;
while (curr < str.length()) {
int candidate = str.indexOf("MIG", curr);
if (candidate == -1) {
// System.out.println("no more prefixes, done scan");
break;
}
String keyStr = "";
for (int i = candidate; i < str.length(); i++, curr++) {
if (str.charAt(i) == '\n') {
// System.out.println("skipping newline");
continue;
}
if (isValidBase64Char(str.charAt(i)) == false) {
// System.out.println("invalid base64 char after: " +
// keyStr);
break;
}
keyStr += str.charAt(i);
if (keyStr.length() == 216) {
break;
}
}
if (keyStr.length() == 216) {
indices.put(candidate, keyStr);
// System.out.println("good key: " + keyStr);
} else {
// System.out.println("bad length: " + keyStr.length() + " / " +
// keyStr);
}
}
return indices;
}
public static boolean isValidBase64Char(char inChar) {
// Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='
return Character.isLetterOrDigit(inChar) || inChar == '+' || inChar == '/' || inChar == '=';
}
public void onClick(ClickEvent event) {
Object sender = event.getSource();
if (sender.equals(nextButton)) {
if (nickBox.getText().length() == 0) {
Window.alert(msg.add_friends_manual_multi_alert_nickname_required());
return;
} else {
final FriendInfoLite friend = new FriendInfoLite();
friend.setSource("Manual");
friend.setBlocked(false);
friend.setCanSeeFileList(!limitedFriendBox.getValue());
friend.setPublicKey(mScannedKeys.get(mScannedKeysByID[currKeyIndex]));
friend.setName(nickBox.getText());
friend.setConnectionId(-1);
friend.setDateAdded(new Date());
String session = OneSwarmRPCClient.getSessionID();
OneSwarmUIServiceAsync service = OneSwarmRPCClient.getService();
nextButton.setEnabled(false);
service.addFriend(session, friend, false, new AsyncCallback<Void>() {
public void onFailure(Throwable caught) {
Window.alert(msg.add_friends_manual_multi_alert_friend_add_failed(caught
.toString()));
nextButton.setEnabled(true);
}
public void onSuccess(Void result) {
if (currKeyIndex + 1 == mScannedKeys.size()) {
callback.cancel();
} else {
generateName = true;
currBehindContext = currAheadContext = 128;
selectKey(++currKeyIndex);
nextButton.setEnabled(true);
}
}
});
}
} else if (sender.equals(skipButton)) {
generateName = true;
if (currKeyIndex + 1 < mScannedKeys.size()) {
currBehindContext = currAheadContext = 128;
selectKey(++currKeyIndex);
} else {
callback.cancel();
}
} else if (sender.equals(moreUpLink)) {
currBehindContext += 64;
selectKey(currKeyIndex);
} else if (sender.equals(moreDownLink)) {
currAheadContext += 64;
selectKey(currKeyIndex);
}
if (mScannedKeys != null) {
if (currKeyIndex + 1 == mScannedKeys.size()) {
nextButton.setText(msg.button_done());
}
} // if scanned keys != null
}
}