package com.cardshifter.gdx.ui.cards;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.NinePatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Touchable;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Dialog;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;
import com.badlogic.gdx.scenes.scene2d.utils.ActorGestureListener;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.scenes.scene2d.utils.NinePatchDrawable;
import com.cardshifter.api.outgoing.CardInfoMessage;
import com.cardshifter.api.outgoing.UsableActionMessage;
import com.cardshifter.gdx.CardshifterGame;
import com.cardshifter.gdx.TargetStatus;
import com.cardshifter.gdx.TargetableCallback;
import com.cardshifter.gdx.ZoomCardCallback;
import com.badlogic.gdx.scenes.scene2d.utils.DragListener;
import com.cardshifter.gdx.screens.DeckBuilderScreen;
import com.cardshifter.gdx.screens.GameScreen;
import com.cardshifter.gdx.ui.CardshifterClientContext;
import com.cardshifter.gdx.ui.res.ResourceView;
import com.cardshifter.gdx.ui.res.ResViewFactory;
import java.util.*;
public class CardViewSmall extends DefaultCardView {
private final Table table;
//private final Label effect;
private final Label namedEffect;
private final Label complexEffect;
private final Label name;
private final ResourceView cost;
private final ResourceView stats;
private final Map<String, Object> properties;
private final int id;
private final CardshifterClientContext context;
private TargetableCallback callback;
private ZoomCardCallback zoomCallback;
private final NinePatch patch = new NinePatch(new Texture(Gdx.files.internal("cardbg.png")), 3, 3, 3, 3);
private final List<UsableActionMessage> actions = new ArrayList<UsableActionMessage>(5);
public boolean isZoomed = false;
public final CardInfoMessage cardInfo;
private final float screenWidth;
private final float screenHeight;
private ClickListener clickListener;
private ActorGestureListener longPressListener;
private DragListener dragListener;
public class MyDragListener extends DragListener {
private Table table;
private float startX = 0;
private float startY = 0;
public MyDragListener(Table table) {
this.table = table;
}
public void drag(InputEvent event, float x, float y, int pointer) {
table.moveBy(x - table.getWidth() / 2, y - table.getHeight() / 2);
}
public void dragStart (InputEvent event, float x, float y, int pointer) {
if (this.startX == 0 && this.startY == 0) {
this.startX = this.table.getX();
this.startY = this.table.getY();
}
}
public void dragStop (InputEvent event, float x, float y, int pointer) {
if (CardViewSmall.this.callback != null) {
if (CardViewSmall.this.callback instanceof DeckBuilderScreen) {
if (!((DeckBuilderScreen)callback).checkCardDrop(CardViewSmall.this)) {
table.addAction(Actions.moveTo(this.startX, this.startY, 0.2f));
}
} else if (CardViewSmall.this.callback instanceof GameScreen) {
if (!((GameScreen)callback).checkCardDrop(CardViewSmall.this)) {
table.addAction(Actions.moveTo(this.startX, this.startY, 0.2f));
} else {
CardViewSmall.this.performAction();
}
}
} else {
table.addAction(Actions.moveTo(this.startX, this.startY, 0.2f));
}
}
}
private void performAction() {
UsableActionMessage action = actions.get(0);
context.sendAction(action);
}
public CardViewSmall(CardshifterClientContext context, CardInfoMessage cardInfo, ZoomCardCallback zoomCallback, boolean zoomedVersion) {
this.context = context;
this.cardInfo = cardInfo;
this.properties = new HashMap<String, Object>(cardInfo.getProperties());
this.id = cardInfo.getId();
this.zoomCallback = zoomCallback;
this.screenWidth = CardshifterGame.STAGE_WIDTH;
this.screenHeight = CardshifterGame.STAGE_HEIGHT;
table = new Table(context.getSkin());
table.setBackground(new NinePatchDrawable(patch));
table.defaults().height(this.screenHeight/30);
Gdx.app.log("CardView", "Creating for " + cardInfo.getProperties());
table.defaults().expand();
name = label(context, cardInfo, "name");
table.add(name).colspan(2).width(this.screenWidth/8).left().row();
// table.add(image);
//effect = label(context, cardInfo, "effect");
this.namedEffect = new Label(" ", context.getSkin());
String resourceName = this.stringResources(cardInfo);
if (resourceName != null && !resourceName.equals("")) {
this.namedEffect.setText(this.stringResources(cardInfo));
}
//effect.setText(effect.getText() + stringResources(cardInfo));
table.add(namedEffect).colspan(2).width(this.screenWidth/8).left().row();
this.complexEffect = label(context, cardInfo, "effect");
table.add(complexEffect).colspan(2).width(this.screenWidth/8).center().row();
if (zoomedVersion) {
Label flavorLabel = label(context, cardInfo, "flavor");
flavorLabel.setWrap(true);
table.add(flavorLabel).colspan(2).width(this.screenWidth/8).center().row();
}
ResViewFactory rvf = new ResViewFactory(context.getSkin());
cost = rvf.forFormat(rvf.res("MANA_COST"), rvf.res("SCRAP_COST"));
table.add(cost.getActor()).colspan(2).right().row();
stats = rvf.forFormat(rvf.coloredRes("ATTACK", properties), rvf.str("/"), rvf.coloredRes("HEALTH", "MAX_HEALTH"));
table.add(label(context, cardInfo, "creatureType")).left();
table.add(stats.getActor()).right();
cost.update(properties);
stats.update(properties);
this.clickListener = new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
if (CardViewSmall.this.dragListener.isDragging()) {
return;
}
if (this.getTapCount() > 1) {
CardViewSmall.this.zoomed();
} else {
CardViewSmall.this.clicked();
}
}
};
this.clickListener.setTapCountInterval(0.2f); //i think that the default is 0.4f
this.longPressListener = new ActorGestureListener(){
@Override
public boolean longPress(Actor actor, float x, float y) {
CardViewSmall.this.zoomed();
return true;
}
};
this.longPressListener.getGestureDetector().setLongPressSeconds(0.3f);
this.dragListener = new MyDragListener(this.table);
table.addListener(this.clickListener);
table.addListener(this.longPressListener);
table.addListener(this.dragListener);
table.setTouchable(Touchable.enabled);
}
private String stringResources(CardInfoMessage cardInfo) {
StringBuilder str = new StringBuilder();
Map<String, Object> props = cardInfo.getProperties();
if (Integer.valueOf(0).equals(props.get("SICKNESS"))) {
str.append(" Rush");
}
if (Integer.valueOf(1).equals(props.get("DENY_COUNTERATTACK"))) {
str.append(" Ranged");
}
return str.toString();
}
private void zoomed() {
if (this.zoomCallback != null) {
this.zoomCallback.zoomCard(this);
}
}
private void clicked() {
Gdx.app.log("CardView", "clicked on " + id);
if (this.zoomCallback != null) {
this.zoomCallback.endZoom(this);
}
if (callback != null) {
callback.addEntity(this);
}
if (!actions.isEmpty()) {
if (actions.size() == 1) {
UsableActionMessage action = actions.get(0);
context.sendAction(action);
}
else {
Dialog dialog = new Dialog("Choose Action", context.getSkin()) {
@Override
protected void result(Object object) {
context.sendAction(actions.get((Integer) object));
}
};
dialog.text("Which action?");
ListIterator<UsableActionMessage> it = actions.listIterator();
while (it.hasNext()) {
int i = it.nextIndex();
UsableActionMessage action = it.next();
dialog.button(action.getAction(), i);
}
dialog.show(context.getStage());
}
}
}
public static Label label(CardshifterClientContext context, CardInfoMessage message, String key) {
Object value = message.getProperties().get(key);
//by changing the following to " ", a row will always be added
//also need to replace newline characters because of some bug on server side
String labelString = String.valueOf(value == null ? " " : value);
labelString = labelString.replace("\n", "").replace("\r", "");
Label label = new Label(labelString, context.getSkin());
label.setEllipsis(true);
return label;
}
@Override
public void set(Object key, Object value) {
if ("HEALTH".equals(key)) {
Integer health = (Integer) value;
Integer oldHealth = (Integer) properties.get(key);
int diff = health - oldHealth;
WidgetGroup grp = (WidgetGroup) table.getParent();
grp.layout();
if (diff != 0) {
Vector2 pos = new Vector2(table.getWidth() / 2, table.getHeight() / 2);
table.localToStageCoordinates(pos);
final Label changeLabel = new Label(String.valueOf(diff), context.getSkin());
Gdx.app.log("Anim", "Create health animation at " + pos.x + ", " + pos.y);
changeLabel.setPosition(pos.x, pos.y);
if (diff > 0) {
changeLabel.setColor(Color.GREEN);
} else {
changeLabel.setColor(Color.RED);
}
changeLabel.addAction(Actions.sequence(Actions.moveBy(0, this.screenHeight/8, 1.5f), Actions.run(new Runnable() {
@Override
public void run() {
changeLabel.remove();
}
})));
context.getStage().addActor(changeLabel);
}
}
properties.put((String) key, value);
cost.update(properties);
stats.update(properties);
}
@Override
public void setTargetable(TargetStatus targetable, TargetableCallback callback) {
table.setColor(targetable.getColor());
this.callback = callback;
}
@Override
public int getId() {
return this.id;
}
@Override
public void usableAction(UsableActionMessage message) {
table.setColor(1, 1, 1, 1f);
actions.add(message);
}
@Override
public void clearUsableActions() {
table.setColor(1, 1, 1, 0.5f);
actions.clear();
}
@Override
public Map<String, Object> getInfo() {
return new HashMap<String, Object>(this.properties);
}
@Override
public Actor getActor() {
return table;
}
public void zoom() {
this.isZoomed = true;
this.name.setEllipsis(false);
this.name.layout();
this.complexEffect.setEllipsis(false);
this.complexEffect.setWrap(true);
this.complexEffect.layout();
}
public void endZoom() {
this.isZoomed = false;
this.name.setEllipsis(true);
this.name.layout();
this.complexEffect.setEllipsis(true);
this.complexEffect.setWrap(false);
this.complexEffect.layout();
}
//workaround for the white border active cards
public void setUsable(TargetableCallback screen) {
this.callback = screen;
}
}