package jp.ac.aiit.jointry.models.blocks.statement.codeblock;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javafx.scene.effect.InnerShadow;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Rectangle;
import jp.ac.aiit.jointry.models.Status;
import jp.ac.aiit.jointry.models.blocks.Block;
import jp.ac.aiit.jointry.models.blocks.Connector;
import jp.ac.aiit.jointry.models.blocks.expression.Condition;
import jp.ac.aiit.jointry.models.blocks.statement.Statement;
import jp.ac.aiit.jointry.util.BlockUtil;
public abstract class CodeBlock extends Statement {
public Set<Statement> childBlocks = new LinkedHashSet<>();
public double hUpper = 80.0;
public double hConcave = BASIC_HEIGHT;
public double hLower = 30.0;
public double wLeft = 20.0;
protected double pHeight = hUpper + hConcave + hLower;
protected Polygon p;
public Connector connector;
public Condition embryo;
public CodeBlock() {
super();
p = new Polygon();
p.setStroke(Color.GRAY);
// override
rightCon.detouch();
rightCon.setWidth(BASIC_WIDTH - wLeft);
rightCon.setHeight(10);
AnchorPane.setTopAnchor(rightCon, hUpper);
AnchorPane.setLeftAnchor(rightCon, wLeft);
connector = new Connector();
connector.detouch();
connector.setWidth(200);
connector.setHeight(50);
connector.setHolder(myBlock);
connector.setPosition(Connector.Position.CENTER);
AnchorPane.setLeftAnchor(connector, 40.0);
AnchorPane.setTopAnchor(connector, 20.0);
Rectangle dip = new Rectangle();
dip.setWidth(198);
dip.setHeight(48);
dip.setFill(Color.web("FAFAFA"));
AnchorPane.setLeftAnchor(dip, 41.0);
AnchorPane.setTopAnchor(dip, 21.0);
InnerShadow innerShadow = new InnerShadow();
innerShadow.setOffsetX(2);
innerShadow.setOffsetY(2);
innerShadow.setColor(Color.web("0x3b596d"));
dip.setEffect(innerShadow);
getChildren().addAll(connector, dip);
}
public void addEmbryo(Condition block) {
this.embryo = block;
block.mother = this;
}
public void accept(Condition c) {
addEmbryo(c);
c.move(getLayoutX() + 40, getLayoutY() + 20);
}
@Override
public void move(double dx, double dy) {
super.move(dx, dy);
if (embryo != null) {
embryo.toFront();
embryo.move(dx + 40, dy + 20);
}
double prevBlockHeight = 0;
if (!childBlocks.isEmpty()) {
for (Block b : childBlocks) {
b.move(dx + wLeft,
dy + hUpper + prevBlockHeight);
prevBlockHeight += b.getHeight();
}
}
}
public void addChild(Statement child) {
childBlocks.add(child);
child.parentBlock = this;
}
public final void resize() {
hConcave = 0;
for (Block b : childBlocks) {
hConcave += b.getHeight();
}
if (hConcave < BASIC_HEIGHT) {
hConcave = BASIC_HEIGHT;
}
pHeight = hUpper + hConcave + hLower;
Double[] polygon = new Double[]{
0.0, 0.0,
BASIC_WIDTH, 0.0,
BASIC_WIDTH, hUpper,
wLeft, hUpper,
wLeft, hUpper + hConcave,
BASIC_WIDTH, hUpper + hConcave,
BASIC_WIDTH, pHeight,
0.0, pHeight
};
setHeight(pHeight);
p.getPoints().clear();
p.getPoints().addAll(polygon);
if (nextBlock != null) {
nextBlock.move(getLayoutX(), getLayoutY() + pHeight);
}
// Parent
if (parentBlock instanceof CodeBlock) {
parentBlock.resize();
}
// 念のため
this.toBack();
}
@Override
public Status getStatus() {
Status status = new Status();
status.put("id", this.getUUID());
if (embryo != null) {
status.put("embryo", BlockUtil.getStatus(embryo));
}
for (Statement state : childBlocks) {
if (state.prevBlock == null) {
List<Status> list = BlockUtil.getAllStatus(state);
status.put("childBlocks", list);
break;
}
}
return status;
}
@Override
public void setStatus(Status status) {
changeable = false; //一時的にリスナーを無効化
this.setUUID((String) status.get("id"));
for (Object key : status.keySet()) {
if (key.equals("embryo")) {
// 変数ブロック
Map embryoStatus = (Map) status.get(key);
Condition emb = (Condition) BlockUtil.create(embryoStatus);
emb.setSprite(getSprite());
emb.setStatus(BlockUtil.convertMapToStatus(status.get(key)));
addEmbryo(emb);
} else if (key.equals("childBlocks")) {
//包含するブロック
ArrayList<Map> list = (ArrayList<Map>) status.get(key);
Block preBlock = null;
for (Map status_info : list) {
Block block = BlockUtil.create(status_info);
block.setSprite(getSprite());
Status childStatus = BlockUtil.convertMapToStatus(status_info.get(block.getClass().getSimpleName()));
block.setStatus(childStatus);
if (preBlock != null) {
//子同士の接続
((Statement) preBlock).addLink((Statement) block);
}
preBlock = block;
//ブロックの包含接続
addChild((Statement) block);
resize();
}
}
}
changeable = true;
}
@Override
public void show() {
super.show();
if (embryo != null) {
embryo.show();
}
for (Statement state : childBlocks) {
if (state.prevBlock == null) {
state.show();
break;
}
}
}
@Override
public String intern() {
StringBuilder sb = new StringBuilder();
if (this.embryo != null) {
sb.append(this.embryo.intern());
}
sb.append(" {\n");
for (Statement p : childBlocks) {
if (p.prevBlock == null) {
sb.append(p.intern());
break;
}
}
sb.append("}\n");
if (nextBlock != null) {
sb.append(nextBlock.intern());
}
return sb.toString();
}
@Override
public void toFront() {
super.toFront();
if (embryo != null) {
embryo.toFront();
}
}
@Override
public void remove() {
super.remove();
if (embryo != null) {
embryo.initializeLink();
}
}
}