package org.vishia.util;

import java.io.IOException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;


/**Outputs the content of a {@link TreeNode_ifc} in a html format to view internal data for debugging.
 * It is used especially for the {@link org.vishia.zbnf.ZbnfParser} parse result.
 * @author Hartmut Schorrig
 *
 */
public class TreeNodeHtmlOutput extends ObjectId
{
  /**Version, history and license.
   * <ul>
   * <li>2017-08-24 Hartmut created. It is similar like {@link DataShow} But for {@link TreeNode_ifc} especially
   * </ul>
   * <br><br>
   * <b>Copyright/Copyleft</b>:
   * For this source the LGPL Lesser General Public License,
   * published by the Free Software Foundation is valid.
   * It means:
   * <ol>
   * <li> You can use this source without any restriction for any desired purpose.
   * <li> You can redistribute copies of this source to everybody.
   * <li> Every user of this source, also the user of redistribute copies
   *    with or without payment, must accept this license for further using.
   * <li> But the LPGL is not appropriate for a whole software product,
   *    if this source is only a part of them. It means, the user
   *    must publish this part of source,
   *    but don't need to publish the whole source of the own product.
   * <li> You can study and modify (improve) this source
   *    for own using or for redistribution, but you have to license the
   *    modified sources likewise under this LGPL Lesser General Public License.
   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
   * </ol>
   * If you are intent to use this sources without publishing its usage, you can get
   * a second license subscribing a special contract with the author. 
   * 
   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de, www.vishia.org
   * 
   */
  public static final String version = "2017-08-24";

  private Queue<Object> newInstances = new ConcurrentLinkedQueue<Object>();

  public static void out(Appendable out, TreeNode_ifc<?, ?> data, boolean bNoHash)
  throws IOException
  {
    TreeNodeHtmlOutput thisz = new TreeNodeHtmlOutput();
    out.append("<html>\n<head><title>DataShow</title></head>");
    out.append("\n<body>\n");
    out.append("\n<p>This file shows the content of the given Java instance and all of its associated instances.\n");
    out.append("\nThe associated instances are able to found by local hyper links inside this file.\n");
    out.append("\nOne can navigate with any browser in all associated instances and back with known &lt;alt-back&gt;.\n");
    out.append("\n</p><p>This file was generated by the java class <code>org/vishia/util/DataShow.java</code> mady by Hartmut Schorrig</p>\n");
    out.append("\n<p>You will find any element usual in the form:</p>\n");
    out.append("\n<ul><li>name : type = value</li></ul>\n");
    out.append("\n<p>Container and arrays are listed with their elements.</p>\n");
    thisz.instanceId(data, thisz.newInstances);  //registers the top level instance, fill newInstances therewith
    Object refData;
    //Any found child is putted into the newInstances. 
    //Write out any new instances.
    while( (refData = thisz.newInstances.poll()) !=null) { //show all instances which are found as reference.
      //while outData is invoked, newInstances is filld with other new instances. 
      TreeNode_ifc<?, ?> refData1 = (TreeNode_ifc<?, ?>) refData;
      thisz.outNode(out, refData1, bNoHash);  //may add further referenced data.
    }
    out.append("\n</body>\n</html>\n");
    
  }
  
  
  /**Output one node independent of there position in the tree.
   * 
   * @param out
   * @param data
   * @param bNoHash
   * @throws IOException
   */
  private void outNode( Appendable out, TreeNode_ifc<?, ?> data, boolean bNoHash)
  throws IOException
  {
    String hash = instanceId(data, newInstances);
    out.append("\n<a name=\"node-").append(hash).append("\"/>");
    out.append("\n  <h3>").append(data.getKey()).append("</h3>");      
    TreeNode_ifc<?,?> parent = data.parent();
    out.append("<p>").append(data.toString()).append("</p>\n");
    if(parent !=null){
      String hashParent = instanceId(parent, newInstances);
      out.append("<p>parent: <a href=\"#node-").append(hashParent).append("\"/>").append(parent.getKey()).append("</p>\n");
    }
    IterableIterator<?> iter = data.iteratorChildren();
    if(iter !=null) {
      out.append("<ul>\n");
      for(Object child: iter) {
        TreeNode_ifc<?,?> child1 = (TreeNode_ifc<?,?>)child;
        out.append("<li>");
        outDataChildren(out, child1);
        out.append("</li>\n");
      }
      out.append("</ul>\n");
    }
  }
  
  
  
  /**Output all children of a node as list of the node
   * 
   * @param out
   * @param data
   * @throws IOException
   */
  private void outDataChildren(Appendable out, TreeNode_ifc<?, ?> data ) throws IOException {
    //Note: don't use the hash code. it may be the best, but the hash produce another content
    //for the same data. Older and newer files are not comparable.
    //faulty: String hash = Integer.toHexString(data.hashCode()); 
    String hash = instanceId(data, newInstances);
    String contentShort = toStringNoHash(data).replace("<", "&lt;");    //< won't be displayed in html.
    out.append(" <a href=\"#node-").append(hash).append("\">")
       .append(" id=").append(data.getKey())
       .append(" = ").append(contentShort)
       .append("</a>")
       //.append(data.toString())  !contentShort
      ;
    }

  }
