package org.jboss.as.console.client.search;

import com.google.gwt.user.client.rpc.AsyncCallback;
import org.jboss.as.console.client.Console;
import org.jboss.as.console.client.core.BootstrapContext;
import org.jboss.as.console.client.core.Footer;
import org.jboss.as.console.client.plugins.AccessControlRegistry;
import org.jboss.as.console.mbui.behaviour.CoreGUIContext;
import org.jboss.as.console.mbui.model.mapping.AddressMapping;
import org.jboss.dmr.client.ModelNode;
import org.jboss.dmr.client.dispatch.DispatchAsync;
import org.jboss.dmr.client.dispatch.impl.DMRAction;
import org.jboss.dmr.client.dispatch.impl.DMRResponse;
import org.jboss.gwt.flow.client.Async;
import org.jboss.gwt.flow.client.Control;
import org.jboss.gwt.flow.client.Function;
import org.jboss.gwt.flow.client.Outcome;
import org.useware.kernel.gui.behaviour.FilteringStatementContext;

import javax.inject.Inject;
import java.util.HashSet;
import java.util.Set;

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

/**
 * Creates search indexes.
 *
 * @author Heiko Braun
 * @date 16/01/14
 */
public class Harvest {

    final AccessControlRegistry accessControlMetaData;
    final DispatchAsync dispatcher;
    final CoreGUIContext statementContext;
    private final BootstrapContext bootstrap;
    private final FilteringStatementContext filteringStatementContext;

    public interface Handler {
        void onStart();
        void onHarvest(String token, String address);
        void onFinish();
        void onError(Throwable t);
    }

    @Inject
    public Harvest(
            AccessControlRegistry accessControlMetaData,
            DispatchAsync dispatcher,
            CoreGUIContext statementContext, final BootstrapContext bootstrap) {

        this.accessControlMetaData = accessControlMetaData;
        this.dispatcher = dispatcher;
        this.statementContext = statementContext;
        this.bootstrap = bootstrap;

        this.filteringStatementContext = new FilteringStatementContext(
                statementContext,
                new FilteringStatementContext.Filter() {
                    @Override
                    public String filter(String key) {

                        if ("selected.entity".equals(key)) {
                            return "*";
                        } else if ("addressable.group".equals(key)) {
                            return bootstrap.getAddressableGroups().isEmpty() ? "*" : bootstrap.getAddressableGroups().iterator().next();
                        } else if ("addressable.host".equals(key)) {
                            return bootstrap.getAddressableHosts().isEmpty() ? "*" : bootstrap.getAddressableHosts().iterator().next();
                        } else {
                            return null;
                        }
                    }

                    @Override
                    public String[] filterTuple(String key) {
                        return null;
                    }
                }
        );
    }

    public void run(final Handler handler) {
        handler.onStart();


        Set<Function> functions = new HashSet<Function>();

        for(final String token : accessControlMetaData.getTokens())
        {

            Set<String> resources = accessControlMetaData.getResources(token);
            for(final String resource : resources)
            {
                // TODO
                if(resource.startsWith("opt:")) continue;

                final ModelNode op = AddressMapping.fromString(resource).asResource(filteringStatementContext);
                op.get(OP).set(READ_RESOURCE_DESCRIPTION_OPERATION);

                Function f = new Function() {
                    @Override
                    public void execute(final Control control) {

                        dispatcher.execute(new DMRAction(op), new AsyncCallback<DMRResponse>() {
                            @Override
                            public void onFailure(Throwable caught) {
                                handler.onError(caught);
                                control.proceed();
                            }

                            @Override
                            public void onSuccess(DMRResponse result) {
                                ModelNode response = result.get();
                                if(response.isFailure())
                                {
                                    handler.onError(new RuntimeException(response.getFailureDescription()));
                                }
                                else
                                {

                                    if(response.hasDefined(RESULT)){
                                        ModelNode desc = response.get(RESULT);
                                        if(desc.hasDefined(DESCRIPTION))
                                        {
                                            String text = desc.get(DESCRIPTION).asString();
                                            // create index
                                            Index.get().add(token, text);
                                            handler.onHarvest(token, op.get(ADDRESS).asString());

                                        }
                                        else
                                        {
                                            System.out.println("Skipped "+token+": "+resource);
                                        }
                                    }

                                }

                                control.proceed();

                            }
                        });
                    }
                } ;

                functions.add(f);

            }
        }


        new Async(Footer.PROGRESS_ELEMENT).parallel(new Outcome() {
            @Override
            public void onFailure(Object context) {
                Console.error("Harvest failed");
            }

            @Override
            public void onSuccess(Object context) {
                handler.onFinish();

            }
        }, functions.toArray(new Function[]{}));

    }
}

@@ -468,16 +468,55 @@
 elNode;%0A
+import org.jboss.dmr.client.ModelType;%0A
 import o
@@ -4673,97 +4673,167 @@
     
-if(response.hasDefined(RESULT))%7B%0A                                        ModelNode desc =
+ModelNode delegate = response.get(RESULT).getType().equals(ModelType.LIST) ?%0A                                            response.get(RESULT).asList().get(0) :
  res
@@ -4851,16 +4851,18 @@
 ESULT);%0A
+%0A%0A
         
@@ -4893,149 +4893,210 @@
     
-    if(desc.hasDefined(DESCRIPTION))%0A                                        %7B%0A                                            String text = desc
+try %7B%0A                                        String text = delegate.hasDefined(DESCRIPTION) ?%0A                                                delegate.get(DESCRIPTION).asString() : delegate.get(RESULT)
 .get
@@ -5117,28 +5117,25 @@
 asString();%0A
-    
+%0A
             
@@ -5218,20 +5218,16 @@
         
-    
 Index.ge
@@ -5280,36 +5280,32 @@
                 
- 
-   
 handler.onHarves
@@ -5342,20 +5342,16 @@
 ing());%0A
-%0A   
         
@@ -5382,102 +5382,32 @@
     
- %7D%0A                                        else%0A                                        %7B%0A    
+%7D catch (Throwable e) %7B%0A
     
@@ -5479,17 +5479,18 @@
 +token+%22
-:
+ %3E
  %22+resou
@@ -5499,50 +5499,8 @@
 e);%0A
-                                        %7D%0A
     

Fix harvest routine (wildcard support)