/*
 * Licensed Materials - Property of Perforce Software, Inc. 
 * © Copyright Perforce Software, Inc. 2014, 2021 
 * © Copyright IBM Corp. 2009, 2014
 * © Copyright ILOG 1996, 2009
 * All Rights Reserved.
 *
 * Note to U.S. Government Users Restricted Rights:
 * The Software and Documentation were developed at private expense and
 * are "Commercial Items" as that term is defined at 48 CFR 2.101,
 * consisting of "Commercial Computer Software" and
 * "Commercial Computer Software Documentation", as such terms are
 * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4,
 * as applicable.
 */

import java.util.Collection;

import ilog.views.IlvGraphic;
import ilog.views.IlvRect;
import ilog.views.sdm.IlvSDMEngine;
import ilog.views.sdm.renderer.IlvFilterSDMRenderer;
import ilog.views.sdm.renderer.IlvRendererUtil;
import ilog.views.sdm.renderer.IlvSDMRenderer;

/**
 * The class <code>FlagRenderer</code> is a filtering renderer that sticks
 * various <code>IlvGraphic</code>s (the flags) to a node. Flags are located in
 * a separate layer, typically over all other layers to have them always
 * visible.
 * 
 * <P>
 * This renderer defines the following graphic properties:
 * <UL>
 * <LI>Flag: An <code>IlvGraphic</code> that represents the decorations.<\LI>
 * <\UL>
 */
public class FlagRenderer extends IlvFilterSDMRenderer {

  private int _flagLayer = 20;
  static final String[] REND_CLASS = { "renderer", "flagRenderer" };
  static final String FLAG = "Flag";
  static final String FLAG_GRAPHICS = "Flag-graphic";
  //////////////////////
  // Constructors

  /**
   * Creates a new flag renderer for a specified filtered renderer.
   */
  public FlagRenderer(IlvSDMRenderer renderer) {
    super(renderer);
  }

  /**
   * Creates a new flag renderer with a <code>null</code> filtered renderer.
   */
  public FlagRenderer() {
    this(null);
  }

  /////////////////////////
  // Bean properties

  /**
   * Sets the flag layer. Default is 20.
   */
  public void setFlagLayer(int v) {
    _flagLayer = v;
  }

  /*
   * Returns the debug level of the current configuration style sheet.
   * 
   * @see setDebugMask
   */
  public int getFlagLayer() {
    return _flagLayer;
  }

  ///////////////////////////
  // Filtering overload

  /**
   * Creates flag.
   */
  Override
  public void addNodeGraphic(IlvSDMEngine engine, java.lang.Object node, IlvGraphic graphic, boolean redraw) {
    super.addNodeGraphic(engine, node, graphic, redraw);
    checkNode(engine, node, graphic);
  }

  /**
   * Recreates flag.
   */
  Override
  public void propertiesChanged(IlvSDMEngine engine, Object object, Collection<String> propertyNames,
      IlvGraphic graphic) {
    super.propertiesChanged(engine, object, propertyNames, graphic);
    if (!engine.getModel().isLink(object)) {
      cleanNode(engine, graphic);
      checkNode(engine, object, graphic);
    }
  }

  /**
   * Clears flag.
   */
  Override
  public void removeNodeGraphic(IlvSDMEngine engine, java.lang.Object node, IlvGraphic graphic, boolean redraw) {
    super.removeNodeGraphic(engine, node, graphic, redraw);
    cleanNode(engine, graphic);
  }

  /**
   * Adjusts flag position.
   */
  Override
  public void nodeGraphicBBoxChanged(IlvSDMEngine engine, java.lang.Object node, IlvGraphic graphic, IlvRect oldBBox,
      IlvRect newBBox, java.lang.String[] pseudoClasses) {
    super.nodeGraphicBBoxChanged(engine, node, graphic, oldBBox, newBBox, pseudoClasses);
    moveFlag(newBBox, (IlvGraphic) graphic.getProperty(FLAG_GRAPHICS));
  }

  //////////////
  // Local method

  // Manage graphic props
  private void checkNode(IlvSDMEngine engine, Object obj, IlvGraphic graphic) {
    if (!graphic.isVisible())
      return;
    Object rawFlag = IlvRendererUtil.getGraphicProperty(engine, obj, FLAG, REND_CLASS, null);
    if (rawFlag != null && rawFlag instanceof IlvGraphic) {
      IlvGraphic g = (IlvGraphic) rawFlag;
      IlvRect r = graphic.boundingBox(null);
      moveFlag(r, g);
      engine.getGrapher().addObject(g, _flagLayer, true);
      graphic.setProperty(FLAG_GRAPHICS, g);
    }
  }

  // Remove previous flag
  private void cleanNode(IlvSDMEngine engine, IlvGraphic graphic) {
    Object previous = graphic.getProperty(FLAG_GRAPHICS);
    if (previous != null) {
      engine.getGrapher().removeObject((IlvGraphic) previous, true);
      graphic.removeProperty(FLAG_GRAPHICS);
    }
  }

  // Adjust flag position
  private void moveFlag(IlvRect newBBox, IlvGraphic source) {
    if (source == null)
      return;
    
    source.move(newBBox.x + newBBox.width - source.boundingBox(null).width, newBBox.y - 12);
  }
}