@Override
  public void undoFromTemplate() {

    if (this.nextWallBuilt == null) {
      for (BlockCoord coord : wallBlocks.keySet()) {
        WallBlock wb = wallBlocks.get(coord);
        ItemManager.setTypeId(coord.getBlock(), wb.getOldId());
        ItemManager.setData(coord.getBlock(), wb.getOldData());
        try {
          wb.delete();
        } catch (SQLException e) {
          e.printStackTrace();
        }
      }

      // Remove this wall chunk.
      ChunkCoord coord = new ChunkCoord(this.getCorner());
      CivGlobal.removeWallChunk(this, coord);
    } else {
      try {
        this.nextWallBuilt.processUndo();
      } catch (CivException e) {
        e.printStackTrace();
      }
    }
  }
  @Override
  public void processUndo() throws CivException {

    double refund = 0.0;
    for (WallBlock wb : wallBlocks.values()) {

      Material material = ItemManager.getMaterial(wb.getOldId());
      if (CivSettings.restrictedUndoBlocks.contains(material)) {
        continue;
      }

      ItemManager.setTypeId(wb.getCoord().getBlock(), wb.getOldId());
      ItemManager.setData(wb.getCoord().getBlock(), wb.getOldData());
      refund += COST_PER_SEGMENT;
      try {
        wb.delete();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }

    refund /= HEIGHT;
    refund = Math.round(refund);
    this.getTown().getTreasury().deposit(refund);
    CivMessage.sendTown(
        this.getTown(), CivColor.Yellow + "Refunded " + refund + " coins from wall construction.");
    try {
      this.delete();
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }
  @Override
  public void delete() throws SQLException {
    if (this.wallBlocks != null) {
      for (WallBlock wb : this.wallBlocks.values()) {
        wb.delete();
      }
    }

    if (wallChunks != null) {
      for (ChunkCoord coord : wallChunks) {
        CivGlobal.removeWallChunk(this, coord);
      }
    }

    super.delete();
  }
  @Override
  public void onMarkerPlacement(Player player, Location next, ArrayList<Location> locs)
      throws CivException {
    BlockCoord first = new BlockCoord(next);
    BlockCoord second = null;

    CultureChunk cc = CivGlobal.getCultureChunk(next);
    if (cc == null || cc.getTown().getCiv() != this.getTown().getCiv()) {
      throw new CivException("Cannot build here, you need to build inside your culture.");
    }

    if (locs.size() <= 1) {
      CivMessage.send(
          player,
          CivColor.LightGray + "First location placed, place another to start building a wall.");
      return;
    }

    // Validate our locations
    if (locs.get(0).distance(locs.get(1)) > Wall.MAX_SEGMENT) {
      throw new CivException(
          "Can only build a wall in "
              + Wall.MAX_SEGMENT
              + " block segments, pick a closer location");
    }

    second = new BlockCoord(locs.get(0));
    locs.clear();
    MarkerPlacementManager.removeFromPlacementMode(player, false);

    Location secondLoc = second.getLocation();
    // Setting to a new block coord so we can increment in buildWallSegment without changing the
    // corner.
    this.setCorner(new BlockCoord(secondLoc));
    this.setComplete(true);
    this.save();

    // We should now be able to draw a line between these two block points.
    HashMap<String, SimpleBlock> simpleBlocks = new HashMap<String, SimpleBlock>();
    int verticalSegments = this.buildWallSegment(player, first, second, 0, simpleBlocks, 0);

    // Pay the piper
    double cost = verticalSegments * COST_PER_SEGMENT;
    if (!this.getTown().getTreasury().hasEnough(cost)) {

      for (WallBlock wb : this.wallBlocks.values()) {
        try {
          wb.delete();
        } catch (SQLException e) {
          e.printStackTrace();
        }
      }
      this.wallBlocks.clear();

      throw new CivException(
          "Cannot build, not enough coins to pay "
              + cost
              + " coins for wall of length "
              + verticalSegments
              + " blocks.");
    }

    this.getTown().getTreasury().withdraw(cost);

    CivMessage.sendTown(
        this.getTown(),
        CivColor.Yellow + "Paid " + cost + " coins for " + verticalSegments + " wall segments.");

    // build the blocks
    for (SimpleBlock sb : simpleBlocks.values()) {
      BlockCoord bcoord = new BlockCoord(sb);
      ItemManager.setTypeId(bcoord.getBlock(), sb.getType());
      ItemManager.setData(bcoord.getBlock(), sb.getData());
    }

    // Add wall to town and global tables
    this.getTown().addStructure(this);
    CivGlobal.addStructure(this);
    this.getTown().lastBuildableBuilt = this;
  }