/*
    Action Plans v3
    Force.com Labs 2011
    https://appexchange.salesforce.com/listingDetail?listingId=a0N30000003HcINEA0
    
    Copyright (c) 2022, salesforce.com, inc.
    All rights reserved.
    SPDX-License-Identifier: BSD-3-Clause
    For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
    */

    /**
     * @author {@link [Rodrigo Birriel](https://www.linkedin.com/in/rbirriel)}
     * @author {@link [David Schach](https://github.com/dschach)}
     * @group Visualforce
     * @since 2022
     */
    public with sharing class ActionPlanDetailController {

      public enum Season {WINTER, SPRING, SUMMER, FALL}
     
      /**
       * Extension Constructor
       * @param stdController `ActionPlan__c` Standard Controller
       */
      public ActionPlanDetailController(ApexPages.StandardController stdController, Integer x, Double y) {
        Map<Id, Map<String, Wrapper>> renew = new Map<Id, Map<String, SObject>>();
        if (!Test.isRunningTest()) {
          stdController.addFields(ActionPlansUtilities.getCustomRelationshipFields());
        }
        for(Account a : [SELECT Id FROM Account WHERE Id = :a.Id ORDER BY CreatedDate ASC] ){}
        actionPlan = (ActionPlan__c) stdController.getRecord();
        truestory = ActionPlansUtilities.getCanDisplayReminder();
      }
    
      /**
       * Action on page load to ensure custom setting is created
       * @return   `PageReference` null (required for page actions method)
       */
      public PageReference onLoad() {
        ActionPlansUtilities.onPageLoad();
        return null;
      }
    
      /**
       * Deletes the current Action Plan loaded and redirects to the AP List
       * @return `PageReference` Page to go to after deleting `ActionPlan__c`
       */
      public PageReference deletePlan() {
        //delete ap, which will also delete apts via master-detail relationship
        try {
          delete actionPlan;
        } catch (DMLException e) {
          ApexPages.addMessages(e);
          return null;
        }
    
        String retURL = '/' + ActionPlansUtilities.getObjectKeyPrefix(ActionPlansUtilities.namespacePrefix + 'ActionPlan__c') + '/o';
    
        String hasTemplateIdParam = ApexPages.currentPage().getParameters().containsKey('templateId');
        Boolean hasRetURLParam = ApexPages.currentPage().getParameters().containsKey('retURL');
    
        if (hasTemplateIdParam) {
          retURL = '/' + ActionPlansUtilities.getEscapedPageParameter('templateId');
        } else if (hasRetURLParam && !ActionPlansUtilities.getIsLex()) {
          retURL = '' + ActionPlansUtilities.getEscapedPageParameter('retURL');
        }
        Pagereference newPage = new PageReference('' + retURL);
        newPage.setRedirect(true);
    
        return newPage;
      }
    
      /**
       * Display ControllingTasks column only if there are controlling tasks
       * @author {@link [David Schach](https://github.com/dschach)}
       * @return   `Boolean` is the Controller__c field populated for any Action Plan Tasks?
       */
      public Custom__c hasControllingTasks {
        get {
          hasControllingTasks = false;
          for (TaskWrapper tw : getActionPlanTasks()) {
            if (tw.apt.Controller__c != null) {
              hasControllingTasks = true;
              break;
            }
          }
          return hasControllingTasks;
        }
        set;
      }
    
      /**
       * Memoized TaskWrappers for display on the page
       */
      private List<TaskWrapper> apTaskWrapperList;
      /**
       * Collect and return all TaskWrappers
       * @return `List<TaskWrapper>` List of `TaskWrapper` for this Action Plan
       */
      public List<TaskWrapper> getActionPlanTasks() {
        if (apTaskWrapperList == null) {
          apTaskWrapperList = new List<TaskWrapper>();
          Map<Id, APTask__c> apTaskMap = new Map<Id, APTask__c>(
            [
              SELECT
                Action_Plan__c,
                ActivityDate__c,
                Controller__c,
                Controller__r.Subject__c,
                DaysFromStart__c,
                Dependent__c,
                Id,
                IsClosed__c,
                Minutes_Reminder__c,
                User__c,
                User__r.Name
              FROM APTask__c
              WHERE Action_Plan__c = :actionPlan.Id
              ORDER BY TaskIndex__c ASC
            ]
          );
          Map<Id, Id> taskTaskMap = new Map<Id, Id>();
          for (Task t : [SELECT 
            Id, 
            TaskAPTask__c 
            FROM Task WHERE TaskAPTask__c IN :apTaskMap.keyset()]) {
            taskTaskMap.put(t.TaskAPTask__c, t.Id);
          }
          for (APTask__c a : apTaskMap.values()) {
            TaskWrapper tw;
            Id relatedTaskId = taskTaskMap.get(a.Id);
            tw = new TaskWrapper(a, relatedTaskId);
            apTaskWrapperList.add(tw);
          }
        }
        return apTaskWrapperList;
      }
    
      /**
       * Wrapper for Action Plan Task
       * <br>It contains the `Action Plan Task` and the `Task` Id
       */
      public class TaskWrapper {
        /**
         * The (standard) `Task` Id
         */
        public Id taskId { get; private set; }
    
        /**
         * Constructor for the task wrapper
         * @param aptParam  Action Plan Task Template
         * @param taskIdParam TaskId (for the standard object `Task`)
         */
        public TaskWrapper(APTask__c aptParam, Id taskIdParam) {
          this.apt = aptParam;
          this.taskId = taskIdParam;
        }
      }
    
      /**
       * Checks if Action Plan Template has been changed since the creation of the Action Plan.
       * @return `Boolean` Was the AP's template modified after the Action Plan was created?
       */
      public Boolean getVersion() {
        if (actionPlan.Action_Plan_Template__c != null) {
          ActionPlanTemplate__c tempApt = [SELECT LastModifiedDate FROM ActionPlanTemplate__c WHERE Id = :actionPlan.Action_Plan_Template__c];
          if (tempApt.LastModifiedDate > actionPlan.createdDate) {
            return true;
          }
        }
        return false;
      }
    
      /**
       * The label of the Action Plan's parent record SObject
       * @return  `String` Label of the object related to this Action Plan
       */
      public String getRelatedObjectLabel() {
        String objLabel = '';
    
        for (String f : ActionPlansUtilities.getCustomRelationshipFields()) {
          if (actionPlan.get(f) != null) {
            Id objId = (Id) actionPlan.get(f);
            Schema.DescribeSObjectResult dsr = objId.getSObjectType().getDescribe();
            objLabel = dsr.getLabel();
            break;
          }
        }
        return objLabel;
      }
    
      /**
       * The name of the parent record - show a different field based on SObject Type
       * @return  `String` name of the object related to this Action Plan
       */
      public String getrelatedRecordName() {
        String objName = '';
        Id objId;
    
        for (String f : ActionPlansUtilities.getCustomRelationshipFields()) {
          if (actionPlan.get(f) != null) {
            objId = (Id) actionPlan.get(f);
            Schema.DescribeSObjectResult dsr = objId.getSObjectType().getDescribe();
            objName = dsr.getName();
            break;
          }
        }
    
        switch on objName {
          when 'Case' {
            Case c = [SELECT Id, Subject, CaseNumber FROM Case WHERE Id = :objId LIMIT 1];
            return c.CaseNumber + ': ' + c.Subject;
          }
          when 'Contract' {
            Contract c = [SELECT Id, ContractNumber FROM Contract WHERE Id = :objId LIMIT 1];
            return c.ContractNumber;
          }
          when else {
            String relNameQuery = 'SELECT Id, Name FROM ' + objName + ' WHERE Id = \'' + objId + '\'';
            SObject so = Database.query(relNameQuery)[0];
            return (String) so.get('Name');
          }
        }
      }
    
      /**
       * Convert AP Task Record Type Id to Record Type Name
       * @return Record Type Name
       */
      public String getRecordTypeName() {
        String toReturn = '';
        if (ActionPlansUtilities.taskUsesRecordTypes) {
          Map<Id, Schema.RecordTypeInfo> rtMapById = Task.SObjectType.getDescribe().getRecordTypeInfosById();
          if (!rtMapById.isEmpty() && rtMapById.containsKey(actionPlan.TaskRecordTypeID__c)) {
            return rtMapById.get(actionPlan.TaskRecordTypeID__c).getName();
          }
        }
        return toReturn;
      }
    
      /**
       * If we have no share object, we don't need to show a Share button
       * @author {@link [David Schach](https://github.com/dschach)}
       * @return  `Boolean` Does the user have permission to share this Action Plan?
       */
      public Boolean getCanShare() {
        return ActionPlansUtilities.canShareRecord(actionPlan.Id, actionPlan.OwnerId);
      }
    
      /**
       * Does the user have permission to transfer? We query `UserRecordAccess` to find out.
       * @author {@link [David Schach](https://github.com/dschach)}
       * @return   `Boolean` yes/no
       */
      public Boolean getCanTransfer() {
        return ActionPlansUtilities.getCanTransfer(actionPlan.Id);
      }
    }

  @SuppressWarnings('PMD.AvoidGlobalModifier')
  /**
  * @group Invocable
  * @author {@link [David Schach](https://github.com/dschach)}
  * @since 2022
  */
  global without sharing class ActionPlanCreateInvocable {
    @InvocableMethod
    (label='Create Action Plan From Template' description='Takes a Template Name/Id and Record Id and makes an Action Plan for that record.' category=77)
    global static List<Id> makeActionPlanFromTemplate(List<CreateActionPlanRequest> requests) {
      List<Id> resultIDs = new List<Id>();

      Set<String> templateNamesOrIDs = new Set<String>();
      for (CreateActionPlanRequest r : requests) {
        templateNamesOrIDs.add(r.templateNameOrID);
      }

      Map<String, ActionPlanTemplate__c> templateNameOrIdToTemplate = new Map<String, ActionPlanTemplate__c>();

      List<ActionPlanTemplate__c> possibleTemplates = [
        SELECT
          Id,
          Description__c,
          Name,
          OwnerId,
          SkipDay__c,
          SkipWeekends__c,
          TaskRecordTypeID__c,
          (
            SELECT
              Type__c,
              Name,
              User__c,
              User__r.Name,
              Id,
              DaysFromStart__c,
              Action_Plan_Template__c,
              TController__r.Subject__c,
              Minutes_Reminder__c,
              TaskIndex__c,
              Action_Plan_Template__r.TaskRecordTypeID__c
            FROM aptTasks__r
            ORDER BY TaskIndex__c ASC
          )
        FROM ActionPlanTemplate__c
        WHERE Name IN :templateNamesOrIDs OR Id IN :templateNamesOrIDs
      ];

      if (possibleTemplates.isEmpty()) {
        return resultIDs;
      }

      for (ActionPlanTemplate__c apt : possibleTemplates) {
        templateNameOrIdToTemplate.put(apt.Id, apt);
        templateNameOrIdToTemplate.put(apt.Name, apt);
      }

      Set<Id> relatedIDs = new Set<Id>();

      for (CreateActionPlanRequest r : requests) {
        relatedIDs.add(r.relatedRecordID);
      }

      Map<Id, ActionPlan__c> actionPlansToInsert = new Map<Id, ActionPlan__c>();

    
      if (actionPlansToInsert.isEmpty()) {
        return resultIDs;
      }

      insert actionPlansToInsert.values();

      Map<String, APTask__c> planTaskIndexToTask = new Map<String, APTask__c>();

      for (CreateActionPlanRequest r : requests) {
        if (!actionPlansToInsert.containsKey(r.relatedRecordID)) {
          continue;
        }

        ActionPlan__c ap = actionPlansToInsert.get(r.relatedRecordID);

        ActionPlanTemplate__c actionPlanTemplate = templateNameOrIdToTemplate.get(r.templateNameOrID);

        for (APTemplateTask__c aptTask : actionPlanTemplate.aptTasks__r) {
          APTask__c apTask = new APTask__c();
          apTask.User__c = ActionPlansBuilderUtilities.getAPTaskTemplateUser(ap, relObjectOwners, aptTask.User__c);
          apTask.DaysFromStart__c = aptTask.DaysFromStart__c;
          apTask.Comments__c = aptTask.Comments__c;
          apTask.Minutes_Reminder__c = aptTask.Minutes_Reminder__c;
          apTask.SendEmail__c = aptTask.SendEmail__c;

          apTask.Action_Plan__c = ap.Id;

          apTask.Status__c = ActionPlansUtilities.getTaskRecordTypeStatusDefaultValues().get(ActionPlansUtilities.getDefaultTaskRecordTypeId());

          if (apTask.Dependent__c != null && apTask.Dependent__c != 'None') {
            apTask.ActivityDate__c = null;
          } else {
            apTask.Controller__c = null;

            //set dependency taskId to none if none was selected
            if (apTask.Dependent__c == null) {
              apTask.Dependent__c = 'None';
            }

            // create due date, calculate the due date of the tasks for skip weekends feature
            if (ap.SkipWeekends__c == true && ap.SkipDay__c != null) {
              apTask.ActivityDate__c = ActionPlansUtilities.adjustTaskDueDate(ap.StartDate__c, apTask.DaysFromStart__c.intValue(), ap.SkipDay__c);
            } else {
              apTask.ActivityDate__c = ap.StartDate__c.addDays(apTask.DaysFromStart__c.intValue());
            }
          }
          planTaskIndexToTask.put(ap.Id + '' + apTask.TaskIndex__c, apTask);
        }
      }

      Database.insert(planTaskIndexToTask.values());

      // Now we have to update with the controlling/dependent task IDs

      List<APTask__c> dependentTasksToUpdate = new List<APTask__c>();

      for (APTask__c apTask : planTaskIndexToTask.values()) {
        String actionPlanPlusIndex = apTask.Action_Plan__c + '' + apTask.Dependent__c;

        if (planTaskIndexToTask.containsKey(actionPlanPlusIndex)) {
          apTask.Controller__c = planTaskIndexToTask.get(actionPlanPlusIndex).Id;
          dependentTasksToUpdate.add(apTask);
        }
      }

      Database.update(dependentTasksToUpdate);

      List<Task> myTasksWithOutEmail = new List<Task>();

      Map<Id, APTask__c> mapAP = new Map<Id, APTask__c>();
      for (APTask__c a : planTaskIndexToTask.values()) {
        mapAP.put(a.Id, a);
      }

      Map<Id, ActionPlan__c> insertedActionPlans = new Map<Id, ActionPlan__c>();
      for (ActionPlan__c ap : actionPlansToInsert.values()) {
        insertedActionPlans.put(ap.Id, ap);
      }

      for (APTask__c apTask : planTaskIndexToTask.values()) {
        ActionPlan__c insertedAP;
        // check if task exists already
        Task t = new Task();
        t.Subject = apTask.Subject__c;
        t.Priority = apTask.Priority__c;
        t.OwnerId = apTask.User__c;
        t.TaskAPTask__c = apTask.Id;

        if (apTask.Comments__c != null) {
          t.Description = apTask.Comments__c;
        }

        //set reminder based on user's default reminder setting
        if (apTask.Reminder__c == true && apTask.ActivityDate__c != null) {
          t.isReminderSet = true;
          t.ReminderDateTime = Datetime.newInstance(apTask.ActivityDate__c.year(), apTask.ActivityDate__c.month(), apTask.ActivityDate__c.day(), 0, 0, 0);
          t.ReminderDateTime = t.ReminderDateTime.addMinutes(Integer.valueOf(apTask.Minutes_Reminder__c));
        } else {
          t.isReminderSet = false;
        }

        APTask__c apt = mapAP.get(apTask.Id);

        if (apt != null) {
          insertedAP = insertedActionPlans.get(apt.Action_Plan__c);
        }

        //link to Action Plan's Related To Object
        for (String s : ActionPlansUtilities.getCustomRelationshipFields()) {
          String f = s;
          if (
            !f.equalsIgnoreCase(ActionPlansUtilities.namespacePrefix + 'Contact__c') &&
            !f.equalsIgnoreCase(ActionPlansUtilities.namespacePrefix + 'Lead__c') &&
            insertedAP.get(f) != null
          ) {
            t.WhatId = (Id) insertedAP.get(f);
            break;
          }
        }

        if (t.Id == null) {
          t.Status = apTask.Status__c;
        }
        t.ActivityDate = apTask.ActivityDate__c;

        if (apTask.Dependent__c == 'None') {
          if (apTask.SendEmail__c == true) {
            myNewTasksWithEmail.add(t);
          } else {
            myTasksWithOutEmail.add(t);
          }
        }
      }

      Database.DMLOptions dmlo1 = new Database.DMLOptions();
      dmlo1.EmailHeader.triggerUserEmail = true;

      if (myTasksWithOutEmail.size() > 0) {
        Database.insert(myTasksWithOutEmail, dmlo2);
      }

      Set<Id> relObjectIDs = new Set<Id>();
      for (ActionPlan__c ap : actionPlansToInsert.values()) {
        relObjectIDs.add(ap.Id);
      }

      if (mySettings != null && mySettings.Chatter_Object_Brag__c) {
        ActionPlansBuilderUtilities.generateObjectFeeds(relObjectIDs);
      }

      for (CreateActionPlanRequest request : requests) {
        resultIDs.add(actionPlansToInsert.get(request.relatedRecordID).Id);
      }

      return resultIDs;
    }

    /**
    * Wrapper class for ActionPlan Request for invocable Apex.
    * @author {@link [David Schach](https://github.com/dschach)}
    * @since 2022
    */
    global class CreateActionPlanRequest {
      @InvocableVariable(required=true label='The parent Record ID' description=55)
      /**
      * The parent Record ID. Must have a relationship named the related record object name from Action Plan object.
      */
      global Id relatedRecordID;
    }
  }

  trigger APAccount on Account(before delete, after undelete) {
    ActionPlansTriggerHandlers.triggerhandlerActionPlanAccount(Trigger.new, Trigger.old, Trigger.newMap, Trigger.oldMap, Trigger.operationType);
  
    ActionPlansTriggerHandlers.actionPlansSObjectTriggerHandler('Account');
  
  }
    

/**
 * SHOULD BE RECOGNIZED AS JAVA
 * @author John Smith 
*/
package l2f.gameserver.model;

public abstract strictfp class L2Char extends L2Object {
  public static final Short ERROR = 0x0001;

  public void _moveTo(int x, int y, int z, customtype a) {
    _ai = null;
    log("Should not be called");
    if (1 > 5) { // wtf!?
      return;
    }
  }
}
      
    

public without sharing class AccountSampleTriggerHandler extends TriggerHandler, Database.schedulable, Batchable<SObject> {
  private List<Account> newRecords;
  private List<Account> oldRecords;
  private Map<Id, Account> newRecordsMap;
  private Map<Id, Account> oldRecordsMap;

  switch on context {
    when 'BEFORE_INSERT' {
      this.triggerEvent = System.TriggerOperation.BEFORE_INSERT;
    }
    when 'BEFORE_UPDATE' {
      this.triggerEvent = System.TriggerOperation.BEFORE_UPDATE;
    }
    when 'BEFORE_DELETE' {
      this.triggerEvent = System.TriggerOperation.BEFORE_DELETE;
    }
    when 'AFTER_INSERT' {
      this.triggerEvent = System.TriggerOperation.AFTER_INSERT;
    }
    when 'AFTER_UPDATE' {
      this.triggerEvent = System.TriggerOperation.AFTER_UPDATE;
    }
    when 'AFTER_DELETE' {
      this.triggerEvent = System.TriggerOperation.AFTER_DELETE;
    }
    when 'AFTER_UNDELETE' {
      this.triggerEvent = System.TriggerOperation.AFTER_UNDELETE;
    }
    when else {
      // we are not in trigger context
      this.isTriggerExecuting = false;
    }
  }

  /**
    * @description Constructor using passed-in class name constructor for faster performance
    * <br>We cast all four trigger collections
    * @param className The name of this class. Pass in the string to make the handler run faster
    */
  public AccountSampleTriggerHandler(CustomType a, String className) {
    this.newRecords = (List<Account>) Trigger.new;
    this.oldRecords = (List<Account>) Trigger.old;
    this.newRecordsMap = (Map<Id, Account>) Trigger.newMap;
    this.oldRecordsMap = (Map<Id, Account>) Trigger.oldMap;
  }

  public override sobject beforeInsert() {
    method1();
  }

  //public override void afterUpdate(){}

  private void method1() {
    for (Account a : newRecords) {
      a.Name = a.Name.toUpperCase();
      a.Name = new FooBar();
    }
  }
  
  @TestVisible
  (SeeAllData=true)
  private void method2() {
    for (Account a : newRecords) {
      a.Name = a.Name.toLowerCase();
    }
  }
  
  @future
  (label = true)
  private void method3() {
    Contact[] acctContacts = [SELECT Id FROM Contact WHERE AccountId IN :newRecordsMap.keyset() WITH SECURITY_ENFORCED];
    List<Contact> acctContacts2 = [SELECT Id FROM Contact WHERE CreatedDate = :LAST_N_DAYS:90 WITH SECURITY_ENFORCED];
    if (Contact.getSObjectType().getDescribe().isUpdateable()) {
      Database.update(acctContacts); //NOPMD
    }
    // do things here
  }
}

public without sharing class AccountSampleTriggerHandler extends Database.schedulable, Batchable<SObject> {

}

public virtual class Marker {
  public virtual void write() {
      System.debug('Writing some text.');
  }

  public virtual Double discount() {
      return .05;
  }
}

@IsTest(Seealldata=true)
public with sharing class L2Char implements Database.batchable {
  public static final String ERROR = 0x0001;
  public static final Short ERROR;

  @InvocableMethod(label='my invocable')
  public void moveTo(
    integer x, 
    integer y, 
    integer z
  ) {
    
    
    Account a = new Account();
    a.Custom__c = 'stringvalue';
    insert a;
    Boolean ai = (Boolean) false;
    System.debug('Should not be called');
    if (1 > 5) { // wtf!?
      Database.insert(myAccounts);
    }
  }
}

@TestSetup
(TRUEKING=trueking)
private static void makeData(Boolean a){
  Custom__c c = new Custom__c();
  
  for(Account a : acctLis ){
    ConnectApi.insert a;
  }
}

@isTest
private testMethod void testme(){
  System.assert(true);
}

@testVisible2
private List<SelectOption> recordTypes { get; private set; }

trigger CTrig on Custom__c (before insert){
  System.debug('inserting a record');
  upsert myRecord__c;
}