/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License;
 * you may not use this file except in compliance with the Elastic License.
 */
package org.elasticsearch.xpack.core.indexlifecycle;

import org.elasticsearch.common.io.stream.Writeable.Reader;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey;

import java.io.IOException;
import java.util.List;

public class RolloverActionTests extends AbstractActionTestCase<RolloverAction> {

    @Override
    protected RolloverAction doParseInstance(XContentParser parser) throws IOException {
        return RolloverAction.parse(parser);
    }

    @Override
    protected RolloverAction createTestInstance() {
        return randomInstance();
    }

    static RolloverAction randomInstance() {
        ByteSizeUnit maxSizeUnit = randomFrom(ByteSizeUnit.values());
        ByteSizeValue maxSize = randomBoolean() ? null : new ByteSizeValue(randomNonNegativeLong() / maxSizeUnit.toBytes(1), maxSizeUnit);
        Long maxDocs = randomBoolean() ? null : randomNonNegativeLong();
        TimeValue maxAge = (maxDocs == null && maxSize == null || randomBoolean())
            ? TimeValue.parseTimeValue(randomPositiveTimeValue(), "rollover_action_test")
            : null;
        return new RolloverAction(maxSize, maxAge, maxDocs);
    }

    @Override
    protected Reader<RolloverAction> instanceReader() {
        return RolloverAction::new;
    }

    @Override
    protected RolloverAction mutateInstance(RolloverAction instance) throws IOException {
        ByteSizeValue maxSize = instance.getMaxSize();
        TimeValue maxAge = instance.getMaxAge();
        Long maxDocs = instance.getMaxDocs();
        switch (between(0, 2)) {
        case 0:
            maxSize = randomValueOtherThan(maxSize, () -> {
                ByteSizeUnit maxSizeUnit = randomFrom(ByteSizeUnit.values());
                return new ByteSizeValue(randomNonNegativeLong() / maxSizeUnit.toBytes(1), maxSizeUnit);
            });
            break;
        case 1:
            maxAge = TimeValue.parseTimeValue(randomPositiveTimeValue(), "rollover_action_test");
            break;
        case 2:
            maxDocs = randomNonNegativeLong();
            break;
        default:
            throw new AssertionError("Illegal randomisation branch");
        }
        return new RolloverAction(maxSize, maxAge, maxDocs);
    }

    public void testNoConditions() {
        IllegalArgumentException exception = expectThrows(IllegalArgumentException.class,
                () -> new RolloverAction(null, null, null));
        assertEquals("At least one rollover condition must be set.", exception.getMessage());
    }

    public void testToSteps() {
        RolloverAction action = createTestInstance();
        String phase = randomAlphaOfLengthBetween(1, 10);
        StepKey nextStepKey = new StepKey(randomAlphaOfLengthBetween(1, 10), randomAlphaOfLengthBetween(1, 10),
                randomAlphaOfLengthBetween(1, 10));
        List<Step> steps = action.toSteps(null, phase, nextStepKey);
        assertNotNull(steps);
        assertEquals(2, steps.size());
        StepKey expectedFirstStepKey = new StepKey(phase, RolloverAction.NAME, RolloverStep.NAME);
        StepKey expectedSecondStepKey = new StepKey(phase, RolloverAction.NAME, UpdateRolloverLifecycleDateStep.NAME);
        RolloverStep firstStep = (RolloverStep) steps.get(0);
        UpdateRolloverLifecycleDateStep secondStep = (UpdateRolloverLifecycleDateStep) steps.get(1);
        assertEquals(expectedFirstStepKey, firstStep.getKey());
        assertEquals(expectedSecondStepKey, secondStep.getKey());
        assertEquals(secondStep.getKey(), firstStep.getNextStepKey());
        assertEquals(action.getMaxSize(), firstStep.getMaxSize());
        assertEquals(action.getMaxAge(), firstStep.getMaxAge());
        assertEquals(action.getMaxDocs(), firstStep.getMaxDocs());
        assertEquals(nextStepKey, secondStep.getNextStepKey());
    }
}

@@ -2019,16 +2019,20 @@
     
+    
 case 0:%0A
     
@@ -2027,16 +2027,20 @@
 case 0:%0A
+    
         
@@ -2099,32 +2099,36 @@
                 
+ 
+   
 ByteSizeUnit max
@@ -2165,32 +2165,36 @@
 Unit.values());%0A
+    
                 
@@ -2298,12 +2298,20 @@
     
+  
+  
 %7D);%0A
+    
     
@@ -2337,16 +2337,20 @@
     
+   
+ 
 case 1:%0A
     
@@ -2345,16 +2345,20 @@
 case 1:%0A
+    
         
@@ -2369,16 +2369,71 @@
 maxAge =
+ randomValueOtherThan(maxAge,%0A                    () -%3E
  TimeVal
@@ -2500,16 +2500,17 @@
 n_test%22)
+)
 ;%0A      
@@ -2507,39 +2507,47 @@
 ));%0A            
+  
+  
 break;%0A
+    
         case 2:%0A
@@ -2558,16 +2558,20 @@
         
+   
+ 
 maxDocs 
@@ -2567,24 +2567,42 @@
    maxDocs =
+ maxDocs == null ?
  randomNonNe
@@ -2605,34 +2605,51 @@
 onNegativeLong()
-;%0A
+ : maxDocs + 1;%0A   
             brea
@@ -2636,39 +2636,44 @@
 %0A               
+ 
 break;%0A
+    
         default:
@@ -2673,16 +2673,20 @@
 efault:%0A
+    
         

Fix RolloverActionTests.mutateInstance