package org.fxmisc.cssfx.test.ui;

/*
 * #%L
 * CSSFX
 * %%
 * Copyright (C) 2014 CSSFX by Matthieu Brouillard
 * %%
 * Licensed 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.
 * #L%
 */


import javafx.scene.control.Label;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import org.fxmisc.cssfx.CSSFX;
import org.fxmisc.cssfx.test.misc.DisabledOnMac;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.testfx.api.FxRobot;
import org.testfx.framework.junit5.ApplicationExtension;
import org.testfx.framework.junit5.Start;

import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

@ExtendWith(ApplicationExtension.class)
public class BasicUITest {
    private BasicUI basicUI;

    @Start
    public void init(Stage stage) throws Exception {
        basicUI = new BasicUI();
        basicUI.start(stage);
    }

    @Test
    public void canRetrieveExpectedNodes(FxRobot robot) throws Exception {
        Runnable stopper = basicUI.startCSSFX();
        try {
            assertThat(robot.lookup(".label").queryAll().size(), is(2));
        } finally {
            stopper.run();
        }
    }
    
    @Test
    public void checkCSSIsApplied(FxRobot robot) throws Exception {
        Runnable stopper = basicUI.startCSSFX();

        try {
            Thread.sleep(1000);
            Label cssfxLabel = robot.lookup("#cssfx").queryAs(Label.class);
            assertThat(cssfxLabel.getTextFill(), is(Color.BLUE));
        } finally {
            stopper.run();
        }
    }

    @Test
    @DisabledOnMac
    public void checkCSSFXCanChangeTheLabelFontColor(FxRobot robot) throws Exception {
        // The CSS used by the UI
        URI basicCSS = BasicUI.class.getResource("basic.css").toURI();
        String basicCSSUrl = basicCSS.toURL().toExternalForm();

        // Resources containing the color changes we want to apply to the CSS 
        URI changedBasicCSSBlue = BasicUI.class.getResource("basic-cssfx-blue.css").toURI();
        URI changedBasicCSSRed = BasicUI.class.getResource("basic-cssfx-red.css").toURI();

        // The file we will tell CSSFX to map the CSS to
        Path mappedSourceFile = Files.createTempFile("tmp", ".css");
        mappedSourceFile.toFile().deleteOnExit();
        
        // Let's start with the normal content first 
        Files.copy(Paths.get(changedBasicCSSBlue), mappedSourceFile, StandardCopyOption.REPLACE_EXISTING);
        
        // start CSSFX
        Runnable stopper = CSSFX.onlyFor(basicUI.getRootNode())
                .noDefaultConverters()
                .addConverter((uri) -> {
                    if (basicCSSUrl.equals(uri)) {
                        return mappedSourceFile;
                    }
                    return null;
                }).start();
        try {
            // We need to let CSSFX some time to detect the file change
            Thread.sleep(1000);
            
            // Let's check that initial launch has used the mapped
            Label cssfxLabel = robot.lookup("#cssfx").queryAs(Label.class);
            assertThat(cssfxLabel.getTextFill(), is(Color.BLUE));

            // Copy the modified version in to the "source" file
            try {
                Files.copy(Paths.get(changedBasicCSSRed), mappedSourceFile, StandardCopyOption.REPLACE_EXISTING);
            } catch (IOException e) {
                e.printStackTrace();
            }

            // We need to let CSSFX some time to detect the file change
            Thread.sleep(1000);

            assertThat(cssfxLabel.getTextFill(), is(Color.RED));
        } finally {
            stopper.run();
        }
    }
}

@@ -749,16 +749,49 @@
 .Color;%0A
+import javafx.scene.paint.Paint;%0A
 import j
@@ -889,16 +889,50 @@
 dOnMac;%0A
+import org.hamcrest.CoreMatchers;%0A
 import o
@@ -1313,16 +1313,149 @@
 Option;%0A
+import java.util.Arrays;%0Aimport java.util.Collection;%0Aimport java.util.Collections;%0A%0Aimport static org.hamcrest.CoreMatchers.hasItem;
 %0Aimport 
@@ -2307,32 +2307,33 @@
 s(Label.class);%0A
+%0A
             asse
@@ -2324,35 +2324,42 @@
             
-assertThat(
+Paint textColor = 
 cssfxLabel.g
@@ -2362,32 +2362,176 @@
 el.getTextFill()
+;%0A            assertThat(%22retrieved color is not one of expected%22, getExpectedTextColor(), hasItem(textColor));%0A            assertThat(textColor
 , is(Color.BLUE)
@@ -4134,35 +4134,42 @@
             
-assertThat(
+Paint textColor = 
 cssfxLabel.g
@@ -4172,32 +4172,176 @@
 el.getTextFill()
+;%0A            assertThat(%22retrieved color is not one of expected%22, getExpectedTextColor(), hasItem(textColor));%0A            assertThat(textColor
 , is(Color.BLUE)
@@ -4641,32 +4641,47 @@
           // We 
+TestMemoryLeaks
 need to let CSSF
@@ -4767,117 +4767,401 @@
     
-assertThat(cssfxLabel.getTextFill(), is(Color.RED));%0A        %7D finally %7B%0A            stopper.run();%0A        %7D
+textColor = cssfxLabel.getTextFill();%0A            assertThat(%22retrieved color is not one of expected%22, getExpectedTextColor(), hasItem(textColor));%0A            assertThat(textColor, is(Color.RED));%0A        %7D finally %7B%0A            stopper.run();%0A        %7D%0A    %7D%0A    %0A    private static Collection%3CPaint%3E getExpectedTextColor() %7B%0A        return Arrays.asList(Color.WHITE, Color.RED, Color.BLUE);
 %0A   

check that returned text color is one of the expected ones defined in relevant CSS