package org.jboss.as.console.client.widgets.forms;

import org.jboss.dmr.client.ModelNode;

import java.util.LinkedList;
import java.util.List;

import static org.jboss.dmr.client.ModelDescriptionConstants.*;

/**
 * Represents entity address meta data, that declared using the {@link Address} annotation.<br/>
 * Address declarations may contain wildcards. An AddressBinding supports replacement of
 * wildcards with proper address values when turned into {@link ModelNode} representations.
 *
 * @author Heiko Braun
 * @date 9/23/11
 */
public class AddressBinding {

    private List<String[]> address = new LinkedList<String[]>();

    public AddressBinding() {
    }

    public void add(String parent, String child)
    {
        address.add(new String[]{parent, child});
    }

    public int getNumWildCards() {

        int counter = 0;

        for(String[] tuple : address)
        {
            if(tuple[0].startsWith("{"))
                counter++;

            if(tuple[1].startsWith("{"))
                counter++;
        }
        return counter;
    }

    /**
     * Turns this address into a ModelNode with an address property.
     *
     * @param args parameters for address wildcards
     * @return a ModelNode with an address property
     */
    public ModelNode asResource(String... args) {
        return asResource(new ModelNode(), args);
    }

    /**
     * Turns this address into a ModelNode with an address property.<br/>
     * This method allows to specify a base address prefix (i.e server vs. domain addressing).
     *
     * @param baseAddress
     * @param args parameters for address wildcards
     * @return a ModelNode with an address property
     */
    public ModelNode asResource(ModelNode baseAddress, String... args) {

        assert getNumWildCards() ==args.length :
                "Address arguments don't match number of wildcards: "+args.length+","+getNumWildCards();

        ModelNode model = new ModelNode();
        model.get(ADDRESS).set(baseAddress);

        int argsCounter = 0;
        for(String[] tuple : address)
        {
            String parent = tuple[0];
            String child = tuple[1];

            if(parent.startsWith("{"))
            {
                parent = args[argsCounter];
                argsCounter++;
            }

            if(child.startsWith("{"))
            {
                child = args[argsCounter];
                argsCounter++;
            }

            model.get(ADDRESS).add(parent, child);
        }

        return model;
    }

    /**
     * Turns this address into a subresource address,
     * including the address and child-type properties.

     *
     * @param args parameters for address wildcards
     * @return  ModelNode including address and child-type property
     */
    public ModelNode asSubresource(String... args) {
        return asSubresource(new ModelNode(), args);
    }

    /**
     * Turns this address into a subresource address,
     * including the address and child-type properties.<br/>
     * The child-type is derived from the last address token qualifier.
     *
     * This method allows to specify a base address prefix (i.e server vs. domain addressing).
     *
     * @param baseAddress
     * @param args parameters for address wildcards
     * @return  ModelNode including address and child-type property
     */
    public ModelNode asSubresource(ModelNode baseAddress, String... args) {

        int numWildCards = getNumWildCards();
        int wildcards = (numWildCards - 1) > 0 ? numWildCards-1 : 0;

        assert wildcards == args.length :
                "Address arguments don't match number of wildcards: "+args.length+","+wildcards;

        ModelNode model = new ModelNode();
        model.get(ADDRESS).set(baseAddress);

        int argsCounter = 0;

        for(int i=0; i<address.size()-1; i++)
        {
            String[] tuple = address.get(i);

            String parent = tuple[0];
            String child = tuple[1];

            if(parent.startsWith("{"))
            {
                parent = args[argsCounter];
                argsCounter++;
            }

            if(child.startsWith("{"))
            {
                child = args[argsCounter];
                argsCounter++;
            }

            model.get(ADDRESS).add(parent, child);
        }

        String[] lastTuple = address.get(address.size()-1);
        String childType = lastTuple[0];

        if(childType.startsWith("{"))
        {
            childType = args[argsCounter];
            argsCounter++;
        }

        model.get(CHILD_TYPE).set(childType);

        return model;

    }
}

@@ -627,16 +627,55 @@
 ng%5B%5D%3E();
+%0A    private int countedWildcards = -1;
 %0A%0A    pu
@@ -849,24 +849,70 @@
 dCards() %7B%0A%0A
+        if(countedWildcards %3C0)%0A        %7B%0A    
         int 
@@ -917,32 +917,36 @@
 t counter = 0;%0A%0A
+    
         for(Stri
@@ -967,34 +967,42 @@
 ddress)%0A        
+ 
-%7B%0A
+   %7B%0A    
             if(t
@@ -1034,32 +1034,36 @@
                 
+  
+  
 counter++;%0A%0A    
@@ -1058,16 +1058,20 @@
 ter++;%0A%0A
+    
         
@@ -1111,32 +1111,36 @@
                 
+  
+  
 counter++;%0A     
@@ -1142,17 +1142,73 @@
         
-%7D
+    %7D%0A%0A            countedWildcards = counter;%0A        %7D%0A
 %0A       
@@ -1217,25 +1217,34 @@
 eturn counte
-r
+dWildcards
 ;%0A    %7D%0A%0A   

improve AddressBinding performance