/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *   SPDX-License-Identifier: Apache-2.0
 */

package org.apache.jena.fuseki.ctl;

import org.apache.jena.atlas.json.JsonValue;
import org.apache.jena.fuseki.servlets.ActionLib;
import org.apache.jena.fuseki.servlets.HttpAction;
import org.apache.jena.fuseki.servlets.ServletOps;
import org.apache.jena.http.HttpMethod;

/** Base for actions that are container and also have actions on items */
public abstract class ActionContainerItem extends ActionCtl {

    protected ActionContainerItem() { super(); }

    @Override
    final
    public void execute(HttpAction action) {
        String method = action.getRequestMethod();
        if ( method.equals(HttpMethod.METHOD_GET) )
            performGet(action);
        else if ( method.equals(HttpMethod.METHOD_POST) )
            performPost(action);
        else if ( method.equals(HttpMethod.METHOD_DELETE) )
            performDelete(action);
        else
            ServletOps.errorMethodNotAllowed(action.getRequestMethod());
    }

    @Override
    public void execOptions(HttpAction action) {
        ActionLib.doOptionsGetPostDeleteHead(action);
        ServletOps.success(action);
    }

    final
    // Container action if the name used to route to the servlet has more path.
    protected boolean isContainerAction(HttpAction action) {
        return (getItemName(action) == null );
    }

    protected void performGet(HttpAction action) {
        JsonValue v;
        if ( isContainerAction(action)  )
            v = execGetContainer(action);
        else
            v = execGetItem(action);

        ServletOps.sendJsonReponse(action, v);
    }

    /** GET request on the container - respond with JSON, or null for plain 200 */
    protected abstract JsonValue execGetContainer(HttpAction action);
    /** GET request on an item in the container - respond with JSON, or null for plain 200 */
    protected abstract JsonValue execGetItem(HttpAction action);

    protected void performPost(HttpAction action) {
        JsonValue v;
        if ( isContainerAction(action) )
            v = execPostContainer(action);
        else
            v = execPostItem(action);

        ServletOps.sendJsonReponse(action, v);
    }

    /** POST request on the container - respond with JSON, or null for plain 200 */
    protected abstract JsonValue execPostContainer(HttpAction action);
    /** POST request on an item in the container - respond with JSON, or null for plain 200 */
    protected abstract JsonValue execPostItem(HttpAction action);


    /** DELETE request */
    protected void performDelete(HttpAction action) {
        if ( isContainerAction(action)  )
            execDeleteContainer(action);
        else
            execDeleteItem(action);
        ServletOps.success(action);
    }

    /** DELETE request on an item in the container */
    protected void execDeleteContainer(HttpAction action) {
        ServletOps.errorMethodNotAllowed(HttpMethod.METHOD_DELETE, "DELETE applied to a container");
    }

    /** DELETE request on an item in the container */
    protected void execDeleteItem(HttpAction action) {
        ServletOps.errorMethodNotAllowed(HttpMethod.METHOD_DELETE);
    }
}
