package com.github.donkirkby.vograbulary.client;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.github.donkirkby.vograbulary.WordDisplay;
import com.github.donkirkby.vograbulary.WordDisplay.WordDisplayListener;
import com.github.donkirkby.vograbulary.bacronyms.BacronymsScreen;
import com.github.donkirkby.vograbulary.bacronyms.Controller;
import com.github.donkirkby.vograbulary.bacronyms.Puzzle;
import com.github.donkirkby.vograbulary.ultraghost.WordList;
import com.google.gwt.animation.client.Animation;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.ParagraphElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Widget;
public class BacronymsPresenter
extends VograbularyPresenter implements BacronymsScreen {
public static final String HISTORY_TOKEN = "bacronyms";
private class WordAnimation extends Animation {
private WordDisplay word;
private double startRotation;
private double targetRotation;
public WordAnimation(WordDisplay word) {
this.word = word;
}
public WordDisplay getWord() {
return word;
}
@Override
protected void onComplete() {
controller.solve();
}
@Override
protected void onUpdate(double progress) {
word.setRotation(
startRotation + (targetRotation - startRotation) * progress);
}
public void rotateWord(double targetRotation) {
startRotation = word.getRotation();
this.targetRotation = targetRotation;
word.setTop(word.getTop());
run(1000);
}
}
private Controller controller;
private Puzzle puzzle;
private State state;
private List<WordDisplay> wordDisplays;
private List<WordAnimation> animations;
private GwtLetterDisplayFactory displayFactory;
private GwtScheduler scheduler = new GwtScheduler();
private WordDisplayListener wordListener = new WordDisplayListener() {
@Override
public void onClick(WordDisplay wordDisplay) {
for (int i = 0; i < animations.size(); i++) {
WordAnimation wordAnimation = animations.get(i);
if (wordAnimation.getWord() == wordDisplay &&
Math.abs(wordDisplay.getRotation()) < 0.0001) {
wordAnimation.rotateWord(Math.PI);
puzzle.setSelectedIndex(i);
}
else {
wordAnimation.rotateWord(0);
}
}
}
};
interface BacronymsCompositeUiBinder extends
UiBinder<Widget, BacronymsPresenter> {
}
@UiField
AbsolutePanel wordPanel;
@UiField
ParagraphElement stateText;
@UiField
Button nextButton;
private static BacronymsCompositeUiBinder uiBinder =
GWT.create(BacronymsCompositeUiBinder.class);
public BacronymsPresenter() {
initWidget(uiBinder.createAndBindUi(this));
displayFactory = new GwtLetterDisplayFactory(wordPanel);
wordDisplays = new ArrayList<>();
animations = new ArrayList<>();
for (int i = 0; i < 3; i++) {
WordDisplay wordDisplay = new WordDisplay(displayFactory);
wordDisplay.addListener(wordListener);
wordDisplays.add(wordDisplay);
animations.add(new WordAnimation(wordDisplay));
}
Window.addResizeHandler(new ResizeHandler() {
@Override
public void onResize(ResizeEvent event) {
layout(3);
}
});
String puzzleLines = Assets.INSTANCE.bacronyms().getText();
String wordListText = Assets.INSTANCE.wordList().getText();
WordList wordList = new WordList();
wordList.read(Arrays.asList(wordListText.split("\\n")));
controller = new Controller();
controller.setScreen(this);
controller.setWordList(wordList);
controller.loadPuzzles(Arrays.asList(puzzleLines.split("\\n")));
controller.next();
}
private void layout(int retries) {
int left = 0;
for (WordDisplay wordDisplay : wordDisplays) {
wordDisplay.setLeft(left);
wordDisplay.setTop(wordDisplay.getTop());
left += wordDisplay.getWidth() + 20;
}
int layoutWidth = wordPanel.getOffsetWidth();
if (retries > 0 && (left < layoutWidth * .75 || layoutWidth < left)) {
float textSize = 0;
boolean isSizeCalculated = false;
for (WordDisplay wordDisplay : wordDisplays) {
if ( ! isSizeCalculated) {
float oldTextSize = wordDisplay.getTextSize();
float correction = layoutWidth * 0.9f / left;
textSize = oldTextSize * correction;
wordPanel.setHeight(textSize * 3 + "px");
isSizeCalculated = true;
}
wordDisplay.setTextSize(textSize);
wordDisplay.setTop((int)textSize);
}
layout(retries-1);
}
}
@Override
public Puzzle getPuzzle() {
return puzzle;
}
@Override
public void setPuzzle(Puzzle puzzle) {
this.puzzle = puzzle;
displayWords();
}
@Override
public State getState() {
return state;
}
@Override
public void setState(State state) {
this.state = state;
stateText.setInnerText(state.name());
nextButton.setVisible(state == State.SOLVED);
}
private void displayWords() {
for (int i = 0; i < 3; i++) {
wordDisplays.get(i).setWord(puzzle.getWord(i));
}
scheduler.scheduleDeferred(new Runnable() {
@Override
public void run() {
layout(3);
}
});
}
@UiHandler("nextButton")
void next(ClickEvent e) {
controller.next();
}
}