content: /*
   *  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
   *
   *        http://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.
   */
  package org.apache.causeway.viewer.wicket.model.models;
  
  import org.apache.wicket.ajax.AjaxRequestTarget;
  
  import org.apache.causeway.applib.value.Blob;
  import org.apache.causeway.applib.value.Clob;
  import org.apache.causeway.applib.value.LocalResourcePath;
  import org.apache.causeway.commons.internal.assertions._Assert;
  import org.apache.causeway.core.metamodel.object.ManagedObject;
  import org.apache.causeway.core.metamodel.object.ManagedObjects;
  import org.apache.causeway.core.metamodel.object.PackedManagedObject;
  import org.apache.causeway.core.security.authentication.logout.LogoutMenu.LoginRedirect;
  import org.apache.causeway.viewer.wicket.model.models.FormExecutor.ActionResultResponseType;
  
  import org.jspecify.annotations.NonNull;
  
  public record ActionResultModel(
      ActionResultResponseType responseType,
      ManagedObject resultAdapter) {
  
      public static ActionResultModel determineFor(
              final @NonNull ActionModel actionModel,
              final ManagedObject resultAdapter,
              final AjaxRequestTarget targetIfAny) {
  
          if(actionModel.columnActionModifier().isForceStayOnPage()) {
              return new ActionResultModel(ActionResultResponseType.RELOAD, resultAdapter);
          }
  
          /*
           * won't implement CAUSEWAY-3372 (reload on void action result)
           * because we found a counter example, where we don't want this behavior, that is:
           * @Action
           * public void delete() {
           *     repositoryService.removeAndFlush(this);
           * }
           */
          if(ManagedObjects.isNullOrUnspecifiedOrEmpty(resultAdapter)) {
              // triage based on whether action return type is 'void'
              return new ActionResultModel(ActionResultResponseType.VOID_AS_EMPTY, resultAdapter);
          }
  
          var resultSpec = resultAdapter.objSpec();
          if (!(resultAdapter instanceof PackedManagedObject)) {
  
              // scalar ...
  
              _Assert.assertTrue(resultSpec.isSingular());
  
              if(LoginRedirect.LOGICAL_TYPE_NAME.equals(resultSpec.logicalTypeName())) {
                  return new ActionResultModel(ActionResultResponseType.SIGN_IN, resultAdapter);
              }
  
              if (resultSpec.isValue()) {
  
                  final Object value = resultAdapter.getPojo();
                  if(value instanceof Clob) {
                      return new ActionResultModel(ActionResultResponseType.VALUE_CLOB, resultAdapter);
                  }
                  if(value instanceof Blob) {
                      return new ActionResultModel(ActionResultResponseType.VALUE_BLOB, resultAdapter);
                  }
                  if(value instanceof LocalResourcePath) {
                      return targetIfAny != null
                              ? new ActionResultModel(ActionResultResponseType.VALUE_LOCALRESPATH_AJAX, resultAdapter)
                              : new ActionResultModel(ActionResultResponseType.VALUE_LOCALRESPATH_NOAJAX, resultAdapter);
                  }
                  if(value instanceof java.net.URL) {
                      return targetIfAny != null
                              ? new ActionResultModel(ActionResultResponseType.VALUE_URL_AJAX, resultAdapter)
                              : new ActionResultModel(ActionResultResponseType.VALUE_URL_NOAJAX, resultAdapter);
                  }
                  // else
                  return new ActionResultModel(ActionResultResponseType.VALUE, resultAdapter);
              } else {
                  return new ActionResultModel(ActionResultResponseType.OBJECT, resultAdapter);
              }
          } else {
              // non-scalar ...
  
              var packedAdapter = (PackedManagedObject) resultAdapter;
              var unpacked = packedAdapter.unpack();
  
              final int cardinality = unpacked.size();
              switch (cardinality) {
              case 1:
                  var firstElement = unpacked.getFirstElseFail();
                  // recursively unwrap
                  return determineFor(actionModel, firstElement, targetIfAny);
              default:
                  return new ActionResultModel(ActionResultResponseType.COLLECTION, resultAdapter);
              }
          }
      }
  
  }
  