package org.openmrs.module.appframework.rest;

import org.apache.commons.lang3.StringUtils;
import org.openmrs.api.context.Context;
import org.openmrs.module.appframework.domain.Extension;
import org.openmrs.module.appframework.service.AppFrameworkService;
import org.openmrs.module.webservices.rest.web.RequestContext;
import org.openmrs.module.webservices.rest.web.RestConstants;
import org.openmrs.module.webservices.rest.web.annotation.PropertyGetter;
import org.openmrs.module.webservices.rest.web.annotation.Resource;
import org.openmrs.module.webservices.rest.web.representation.Representation;
import org.openmrs.module.webservices.rest.web.resource.api.PageableResult;
import org.openmrs.module.webservices.rest.web.resource.api.Searchable;
import org.openmrs.module.webservices.rest.web.resource.impl.BaseDelegatingReadableResource;
import org.openmrs.module.webservices.rest.web.resource.impl.DelegatingResourceDescription;
import org.openmrs.module.webservices.rest.web.resource.impl.NeedsPaging;

import java.util.List;

@Resource(name = RestConstants.VERSION_1 + "/extension", supportedClass = Extension.class, supportedOpenmrsVersions = {"1.9.*", "1.10.*", "1.11.*", "1.12.*", "2.0.*"})
public class ExtensionResource extends BaseDelegatingReadableResource<Extension> implements Searchable {

    private AppFrameworkService getService() {
        return Context.getService(AppFrameworkService.class);
    }

    @Override
    public Extension getByUniqueId(String uid) {
        for (Extension candidate : getService().getAllEnabledExtensions()) {
            if (candidate.getId().equals(uid)) {
                return candidate;
            }
        }
        return null;
    }

    @Override
    public Extension newDelegate() {
        return new Extension();
    }

    @Override
    public DelegatingResourceDescription getRepresentationDescription(Representation representation) {
        DelegatingResourceDescription description = new DelegatingResourceDescription();
        description.addProperty("uuid"); // expose "id" as "uuid" for consistency with other REST resources
        description.addProperty("display");
        description.addSelfLink();
        if (representation == Representation.DEFAULT) {
            description.addProperty("appId");
            description.addProperty("extensionPointId");
            description.addProperty("type");
            description.addProperty("label");
            description.addProperty("url");
            description.addProperty("icon");
            description.addProperty("order");
            description.addProperty("requiredPrivilege");
            description.addProperty("featureToggle");
            description.addProperty("require");
            description.addProperty("script");
            description.addProperty("extensionParams");
            description.addProperty("belongsTo", Representation.REF);
        }
        return description;
    }

    @PropertyGetter("uuid")
    public String getUuid(Extension delegate) {
        return delegate.getId();
    }

    @PropertyGetter("display")
    public String getDisplay(Extension delegate) {
        return delegate.getId();
    }

    /**
     * Supports request parameters (both optional):
     * * "extensionPoint"
     * * "scope" = "user" if not user, then all enabled extensions)
     * @param context
     * @return enabled extensions matching the request parameters
     */
    @Override
    protected PageableResult doSearch(RequestContext context) {
        String extensionPointId = context.getParameter("extensionPoint");
        boolean userOnly = "user".equals(context.getParameter("scope"));
        AppFrameworkService service = getService();
        List<Extension> results;
        if (userOnly) {
            if (StringUtils.isEmpty(extensionPointId)) {
                results = service.getExtensionsForCurrentUser();
            }
            else {
                results = service.getExtensionsForCurrentUser(extensionPointId);
            }
        }
        else {
            if (StringUtils.isEmpty(extensionPointId)) {
                results = service.getAllEnabledExtensions();
            }
            else {
                results = service.getAllEnabledExtensions(extensionPointId);
            }
        }
        return new NeedsPaging<Extension>(results, context);
    }
}

@@ -40,16 +40,287 @@
 .rest;%0A%0A
+import io.swagger.models.Model;%0Aimport io.swagger.models.ModelImpl;%0Aimport io.swagger.models.properties.IntegerProperty;%0Aimport io.swagger.models.properties.MapProperty;%0Aimport io.swagger.models.properties.RefProperty;%0Aimport io.swagger.models.properties.StringProperty;%0A
 import o
@@ -780,32 +780,199 @@
 ation.Resource;%0A
+import org.openmrs.module.webservices.rest.web.representation.DefaultRepresentation;%0Aimport org.openmrs.module.webservices.rest.web.representation.FullRepresentation;%0A
 import org.openm
@@ -4791,11 +4791,1248 @@
 );%0A    %7D
+%0A%0A    @Override%0A    public Model getGETModel(Representation rep) %7B%0A        ModelImpl modelImpl = (ModelImpl) super.getGETModel(rep);%0A%0A        modelImpl%0A                .property(%22uuid%22, new StringProperty())%0A                .property(%22display%22, new StringProperty());%0A%0A        if (rep instanceof DefaultRepresentation) %7B%0A            modelImpl%0A                    .property(%22appId%22, new StringProperty())%0A                    .property(%22extensionPointId%22, new StringProperty())%0A                    .property(%22type%22, new StringProperty())%0A                    .property(%22label%22, new StringProperty())%0A                    .property(%22url%22, new StringProperty())%0A                    .property(%22icon%22, new StringProperty())%0A                    .property(%22order%22, new IntegerProperty())%0A                    .property(%22requiredPrivilege%22, new StringProperty())%0A                    .property(%22featureToggle%22, new StringProperty())%0A                    .property(%22require%22, new StringProperty())%0A                    .property(%22script%22, new StringProperty())%0A                    .property(%22extensionParams%22, new MapProperty(new StringProperty()))%0A                    .property(%22belongsTo%22, new RefProperty());%0A        %7D%0A        return modelImpl;%0A    %7D
 %0A%7D%0A

Document ExtensionResource (#20)