package mil.nga.mapcache.wizards.createtile;

import android.app.Activity;
import android.util.Log;

import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Stack;

import javax.xml.parsers.ParserConfigurationException;

import mil.nga.mapcache.io.network.HttpClient;
import mil.nga.mapcache.io.network.IResponseHandler;
import mil.nga.mapcache.ogc.wms.CapabilitiesParser;
import mil.nga.mapcache.ogc.wms.Layer;
import mil.nga.mapcache.ogc.wms.WMSCapabilities;

/**
 * Provides the layers from a particular tile server if that tile server has multiple layers.
 * Otherwise it will populate the model with an empty array of layers.
 */
public class LayersProvider implements IResponseHandler {

    /**
     * The activity used to get back on the main thread.
     */
    private Activity activity;

    /**
     * The server url.
     */
    private String url;

    /**
     * The model to populate with layer information.
     */
    private LayersModel model;

    /**
     * Constructs a new layer provider.
     *
     * @param activity The activity used to get back on the main thread.
     * @param model    The model to populate with layer information.
     */
    public LayersProvider(Activity activity, LayersModel model) {
        this.activity = activity;
        this.model = model;
    }

    /**
     * Retrieves a list of layers from the specified url.  It does this on a background thread
     * and the layer will then be populated within the model and that population is done on the
     * main thread.
     *
     * @param url The url to retrieve layers from.
     */
    public void retrieveLayers(String url) {
        if (url.toLowerCase().contains("wms")) {
            String capabilitiesUrl = url + "request=GetCapabilities&version=1.3.0&service=WMS";
            HttpClient.getInstance().sendGet(capabilitiesUrl, this);
        } else {
            model.setLayers(new LayerModel[0]);
        }
    }

    @Override
    public void handleResponse(InputStream stream) {
        CapabilitiesParser parser = new CapabilitiesParser();
        try {
            WMSCapabilities capabilities = parser.parse(stream);
            List<LayerModel> allLayers = new ArrayList<>();
            Stack<Layer> parents = new Stack<>();
            for (Layer layer : capabilities.getCapability().getLayer()) {
                getLayers(allLayers, layer, parents);
            }
            final LayerModel[] allLayersArray = allLayers.toArray(new LayerModel[allLayers.size()]);
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    model.setLayers(allLayersArray);
                }
            });
        } catch (ParserConfigurationException | SAXException | IOException e) {
            model.setLayers(new LayerModel[0]);
            Log.e(LayersProvider.class.getSimpleName(),
                    "Unable to parse WMS GetCapabilities document", e);
        }
    }

    @Override
    public void handleException(IOException exception) {
        model.setLayers(new LayerModel[0]);
        Log.e(LayersProvider.class.getSimpleName(), "WMS GetCapabilities failed: ", exception);
    }

    /**
     * Recursively gets the layer's and their info.
     *
     * @param allLayers The list to add the layer info too.
     * @param layer     The current layer we are gathering info for.
     * @param parents   The stack of parents for the layer.
     */
    private void getLayers(List<LayerModel> allLayers, Layer layer, Stack<Layer> parents) {
        if (!layer.getName().isEmpty()) {
            LayerModel model = new LayerModel();
            String title = parents.get(0).getTitle();
            String description = "";
            for (int i = 1; i < parents.size(); i++) {
                description += parents.get(i).getTitle() + " ";
            }
            description += layer.getTitle();
            model.setName(layer.getName());
            model.setTitle(title);
            model.setDescription(description);
            allLayers.add(model);
        }

        if (!layer.getLayers().isEmpty()) {
            parents.push(layer);
            for (Layer child : layer.getLayers()) {
                getLayers(allLayers, child, parents);
            }
            parents.pop();
        }
    }
}

@@ -3152,24 +3152,134 @@
 xception) %7B%0A
+        activity.runOnUiThread(new Runnable() %7B%0A            @Override%0A            public void run() %7B%0A        
         mode
@@ -3302,32 +3302,58 @@
 LayerModel%5B0%5D);%0A
+            %7D%0A        %7D);%0A
         Log.e(La

Handle layers exception on UI thread