include(Resources.id("mtrsteamloco:scripts/display_helper.js"));
importPackage(java.awt);
importPackage(java.awt.geom);
importPackage(java.io);
importPackage(java.net);
importPackage(java.util);
importPackage(java.lang);
importPackage(java.util.concurrent);

const top_text = new ConfigResponder.TextField("top_text", ComponentUtil.translatable("上部テキスト"), "特急");
const top_text_color = new ConfigResponder.TextField("top_text_color", ComponentUtil.translatable("上部テキスト色"), "150,0,0");
const middle_text = new ConfigResponder.TextField("middle_text", ComponentUtil.translatable("中間部テキスト"), "乗車口");
const middle_color = new ConfigResponder.TextField("middle_color", ComponentUtil.translatable("中間部色"), "200,200,0");
const bottom_text = new ConfigResponder.TextField("bottom_text", ComponentUtil.translatable("下部テキスト"), "1号車");

let slotCfg = {
  "version": 1,
  "texSize": [50, 100],
  "slots": [{
    "name": "main",
    "texArea": [0, 0, 50, 100],
    "pos": [[[-0.1875, 2.86875, 0], [-0.1875, 2.11875, 0], [0.1875, 2.11875, 0], [0.1875, 2.86875, 0]]],
    "offsets": [[0, 0, 0.01]]
  }]
};
let dhBase = new DisplayHelper(slotCfg);
let activeLCDs = [];
let asyncPool = null;

function create(ctx, state, entity) {
  state.dh = dhBase.create();
  state.displayRate = new RateLimit(2.0);
  state.font = Resources.readFont(Resources.id("mtrsteamloco:eyecandies/font/notosansjp/notosansjp.ttf"));


  activeLCDs.push({ ctx: ctx, state: state, entity: entity });

  if (Resources.ANTE_FLAG && asyncPool === null) {
    asyncPool = Executors.newScheduledThreadPool(1);
    asyncPool.scheduleAtFixedRate(new java.lang.Runnable({
      run: () => {
        for (let i = 0; i < activeLCDs.length; i++) {
          let entry = activeLCDs[i];
          if (!entry.state.dh || entry.state.dh.closed) continue;

          try {
            tick(entry.ctx, entry.state, entry.entity);
            entry.ctx.drawCalls.put(
              i,
              new ClusterDrawCall(entry.state.dh.model, new Matrix4f())
            );
          } catch (e) {
            print(e);
          }
        }
      }
    }), 0, 1000 / 0.5, TimeUnit.MILLISECONDS);
  }
}

function dispose(ctx, state, entity) {
  for (let i = activeLCDs.length - 1; i >= 0; i--) {
    if (activeLCDs[i].entity.equals(entity)) {
      activeLCDs.splice(i, 1);
      break;
    }
  }

  if (activeLCDs.length === 0 && asyncPool !== null) {
    asyncPool.shutdown();
    asyncPool = null;
  }
  state.dh.close();
}

function render(ctx, state, entity) {
  entity.registerCustomConfig(top_text);
  entity.registerCustomConfig(top_text_color);
  entity.registerCustomConfig(middle_text);
  entity.registerCustomConfig(middle_color);
  entity.registerCustomConfig(bottom_text);

  if (!Resources.ANTE_FLAG) {
    tick(ctx, state, entity);
    ctx.drawModel(state.dh.model, null);
  }
}

function stringToColor(colorStr) {
    if (!colorStr) return new Color(0.0, 0.0, 0.0);
    
    let parts = colorStr.split(",");
    if (parts.length !== 3) return new Color(0.0, 0.0, 0.0);

    return new Color(
        parseFloat(parts[0].trim()) / 255,
        parseFloat(parts[1].trim()) / 255,
        parseFloat(parts[2].trim()) / 255
    );
}

function tick(ctx, state, entity) {
  let topText = entity.getCustomConfig("top_text");
  let topColor = stringToColor(entity.getCustomConfig("top_text_color"));
  let middleText = entity.getCustomConfig("middle_text");
  let middleColor = stringToColor(entity.getCustomConfig("middle_color"));
  let bottomText = entity.getCustomConfig("bottom_text");

  let g;
  g = state.dh.graphicsFor("main");

  g.setComposite(AlphaComposite.Clear);
  g.fillRect(0, 0, 50, 100);
  g.setComposite(AlphaComposite.SrcOver);

  //top
  assyukuDraw(g, topText, 15, 20, 50, state.font, topColor, 0);

  //middle
  g.setColor(middleColor);
  g.fillRect(5, 30, 40, 15);
  assyukuDraw(g, middleText, 15, 43, 40, state.font, Color.white, 5);

  //bottom
  assyukuDraw(g, bottomText, 15, 90, 50, state.font, Color.black, 0);

  state.dh.upload();
}

function assyukuDraw(g, text, textSize, drawPos, targetWidth, font, textColor, offsetX) {
  let fm = g.getFontMetrics(font.deriveFont(Font.PLAIN, textSize));

  if (fm.stringWidth(text) > targetWidth) {
    let nextStaScale = targetWidth / fm.stringWidth(text);
    // ★スケール適用フォント
    g.setFont(font.deriveFont(AffineTransform.getScaleInstance(nextStaScale, 1.0)).deriveFont(Font.PLAIN, textSize));
    // ★スケール後の実際の幅で中央揃え！
    let scaledWidth = fm.stringWidth(text) * nextStaScale;
    let startX = offsetX + ((targetWidth - scaledWidth) / 2);
    g.setColor(textColor);
    g.drawString(text, startX, drawPos);
  } else {
    // ★スケール不要時も中央揃え
    g.setFont(font.deriveFont(Font.PLAIN, textSize));
    g.setColor(textColor);
    let currentWidth = fm.stringWidth(text);
    let startX = offsetX + ((targetWidth - currentWidth) / 2);
    g.drawString(text, startX, drawPos);
  }
}

function assyukuDrawNotCenter(g, text, textSize, drawPos, targetWidth, font, textColor, offsetX) {
  let originalFont = font.deriveFont(Font.PLAIN, textSize);
  let fm = g.getFontMetrics(originalFont);


  if (fm.stringWidth(text) > targetWidth) {
    let scale = targetWidth / fm.stringWidth(text);
    let scaledFont = font.deriveFont(AffineTransform.getScaleInstance(scale, 1.0))
      .deriveFont(Font.PLAIN, textSize);
    g.setFont(scaledFont);
    g.setFont(scaledFont);  // ★2回セット
    g.setColor(textColor);
    g.drawString(text, offsetX, drawPos);
  } else {
    g.setFont(originalFont);
    g.setColor(textColor);
    g.drawString(text, offsetX, drawPos);
  }
}

function use(ctx, state, entity, player) {

}