/*

Copyright: All contributers to the Umple Project

This file is made available subject to the open source license found at:
http://umple.org/license

This file analyze layout related umple meta model tokens such positions and 
populates the umple meta model.

Please refer to UmpleInternalParser.ump for more details.

*/

namespace cruise.umple.compiler;

class UmpleInternalParser
{
   after init {
     parser.addGrammarFile("/layout/umple_layout.grammar");
  }


  // Analyze layout tokens to the Umple language
  private void analyzeLayoutToken(Token token, int analysisStep)
  {
  }

  // There are currently no core tokens of concern in the context of an UmpleClass
  // This method is available if needed
  private void analyzeLayoutToken(Token token, UmpleClassifier inUmpleClassifier, int analysisStep)
  {
    // Only process layout tokens once all other entities have been analyzed
    if (analysisStep == 1 || shouldProcessClassAgain)
    {
      shouldProcessClassAgain = true;
      return;
    }
  
    if (token.is("elementPosition"))
    {
      inUmpleClassifier.setCoordinates(new Coordinate(token.getIntValue("x"),token.getIntValue("y"), token.getIntValue("width"), token.getIntValue("height")));
    }
    else if (token.is("displayColor"))
    { // See near clone in UmpleInternalParser_CodeClass.ump
      String theColor = token.getValue("colorValue");
      if(theColor.startsWith("=")) theColor=theColor.substring(1,theColor.length());
      if(!theColor.startsWith("\"")) theColor= "\""+theColor;
      if(!theColor.endsWith("\"")) theColor= theColor+"\"";
      inUmpleClassifier.setDisplayColor(theColor);
    }
    mixset Association {
      else if (token.is("associationPosition"))
      {
        String name = token.getValue("name");
        Association assoc = model.getAssociation(name);

        if (assoc != null)
        {
          assoc.setName(name);
          for(Token position : token.getSubTokens())
          {
            if (position.is("coordinate"))
            {
              assoc.addPosition(new Coordinate(position.getIntValue("x"),position.getIntValue("y"),0,0));
            }
          }
        }
      }
    }
  }

  // Perform post token analysis on core elements of the Umple language
  private void postTokenLayoutAnalysis()
  {
    layoutNewElements();
  }  

  // Look for any new elements and give them positions if undefined
  private void layoutNewElements()
  {
    // layout classes
    for (int i=0; i<model.numberOfUmpleClasses(); i++)
    {
      UmpleClass c = model.getUmpleClass(i);

      if (c.getCoordinates().getStatus() == Coordinate.Status.Defaulted)
      {
        // Do nothing
      }
      else if (c.getCoordinates().getStatus() == Coordinate.Status.Undefined)
      {
        c.setCoordinates(model.getDefaultClassPosition(i+1));
        c.getCoordinates().setStatus(Coordinate.Status.Defaulted);
      }
    }

    // layout interfaces
    for (int i=0; i<model.numberOfUmpleInterfaces(); i++)
    {
      UmpleInterface c = model.getUmpleInterface(i);

      if (c.getCoordinates().getStatus() == Coordinate.Status.Defaulted)
      {
        // Do nothing
      }
      else if (c.getCoordinates().getStatus() == Coordinate.Status.Undefined)
      {
        c.setCoordinates(model.getDefaultInterfacePosition(i+1));
        c.getCoordinates().setStatus(Coordinate.Status.Defaulted);
      }
    }
    mixset Association {
      // Layout associations
      for (int i=0; i<model.numberOfAssociations(); i++)
      {
        Association a = model.getAssociation(i);
        
        if (associationIsBetweenClassAndInterface (a)){continue;}
        if (associationIsBetweenClassAndTrait (a)){continue;}
        
        int numberOfPositions = a.numberOfPositions();

        if (numberOfPositions < 2)
        {
          Coordinate[] defaults = model.getDefaultAssociationPosition(a);
      if (defaults==null) continue;
          a.addPosition(defaults[0]);
          a.addPosition(defaults[1]);
          a.getPosition(0).setStatus(Coordinate.Status.Defaulted);
          a.getPosition(1).setStatus(Coordinate.Status.Defaulted);
        }
      }
    }    
  }  

} 
