// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ui;

import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.scale.JBUIScale;
import com.intellij.ui.scale.ScaleType;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.SystemProperties;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import sun.java2d.SunGraphicsEnvironment;

import java.awt.*;
import java.lang.reflect.Method;
import java.util.concurrent.atomic.AtomicReference;

public final class JreHiDpiUtil {
  private static final AtomicReference<Boolean> jreHiDPI = new AtomicReference<>();
  private static volatile boolean jreHiDPI_earlierVersion;

  /**
   * Returns whether the JRE-managed HiDPI mode is enabled and the graphics configuration represents a HiDPI device.
   * (analogue of {@link UIUtil#isRetina(Graphics2D)} on macOS)
   */
  public static boolean isJreHiDPI(@Nullable GraphicsConfiguration gc) {
    return isJreHiDPIEnabled() && JBUIScale.isHiDPI(JBUIScale.sysScale(gc));
  }

  /**
   * Returns whether the JRE-managed HiDPI mode is enabled and the graphics represents a HiDPI device.
   * (analogue of {@link UIUtil#isRetina(Graphics2D)} on macOS)
   */
  public static boolean isJreHiDPI(@Nullable Graphics2D g) {
    return isJreHiDPIEnabled() && JBUIScale.isHiDPI(JBUIScale.sysScale(g));
  }

  /**
   * Returns whether the JRE-managed HiDPI mode is enabled.
   * (True for macOS JDK >= 7.10 versions)
   *
   * @see ScaleType
   */
  public static boolean isJreHiDPIEnabled() {
    if (jreHiDPI.get() != null) return jreHiDPI.get();

    synchronized (jreHiDPI) {
      if (jreHiDPI.get() != null) return jreHiDPI.get();

      jreHiDPI.set(false);
      if (!SystemProperties.getBooleanProperty("hidpi", true)) {
        return false;
      }
      jreHiDPI_earlierVersion = true;
      if (SystemInfo.isJetBrainsJvm) {
        try {
          GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
          if (ge instanceof SunGraphicsEnvironment) {
            Method m = ReflectionUtil.getDeclaredMethod(SunGraphicsEnvironment.class, "isUIScaleEnabled");
            jreHiDPI.set(m != null && (Boolean)m.invoke(ge));
            jreHiDPI_earlierVersion = false;
          }
        }
        catch (Throwable ignore) {
        }
      }
      if (SystemInfo.isMac) {
        jreHiDPI.set(true);
      }
      return jreHiDPI.get();
    }
  }

  /**
   * Indicates earlier JBSDK version, not containing HiDPI changes.
   * On macOS such JBSDK supports jreHiDPI, but it's not capable to provide device scale
   * via GraphicsDevice transform matrix (the scale should be retrieved via DetectRetinaKit).
   */
  @ApiStatus.Internal
  public static boolean isJreHiDPI_earlierVersion() {
    isJreHiDPIEnabled();
    return jreHiDPI_earlierVersion;
  }

  @TestOnly
  @NotNull
  public static AtomicReference<Boolean> test_jreHiDPI() {
    if (jreHiDPI.get() == null) {
      // force init
      isJreHiDPIEnabled();
    }
    return jreHiDPI;
  }
}

@@ -1766,60 +1766,67 @@
     
-if (jreHiDPI.get() != null) return jreHiDPI.get();%0A%0A
+Boolean value = jreHiDPI.get();%0A    if (value == null) %7B%0A  
     
@@ -1853,28 +1853,34 @@
 PI) %7B%0A      
-if (
+  value = 
 jreHiDPI.get
@@ -1885,75 +1885,70 @@
 et()
- != null) return jreHiDPI.get();%0A%0A      jreHiDPI.set(
+;%0A        if (value == null) %7B%0A          value = 
 false
-)
 ;%0A      
 if (
@@ -1947,13 +1947,16 @@
     
+    
 if (
-!
 Syst
@@ -2015,32 +2015,8 @@
     
-  return false;%0A      %7D%0A
     
@@ -2051,24 +2051,30 @@
 true;%0A      
+      
 if (SystemIn
@@ -2090,24 +2090,30 @@
 rainsJvm) %7B%0A
+      
         try 
@@ -2124,16 +2124,22 @@
         
+      
 Graphics
@@ -2202,24 +2202,30 @@
 ironment();%0A
+      
           if
@@ -2278,16 +2278,22 @@
         
+      
 Method m
@@ -2391,29 +2391,30 @@
         
-jreHiDPI.set(
+      value = 
 m != nul
@@ -2439,17 +2439,16 @@
 voke(ge)
-)
 ;%0A      
@@ -2445,32 +2445,38 @@
 e);%0A            
+      
 jreHiDPI_earlier
@@ -2506,20 +2506,16 @@
     
-%7D%0A  
       %7D%0A
     
@@ -2506,24 +2506,46 @@
           %7D%0A
+              %7D%0A      
         catc
@@ -2575,24 +2575,44 @@
         
+      %7D%0A            
 %7D%0A      
 %7D%0A      
@@ -2599,26 +2599,24 @@
     %7D%0A      
-%7D%0A
       if (Sy
@@ -2645,34 +2645,34 @@
     
-jreHiDPI.set(
+      value = 
 true
-)
 ;%0A      
 %7D%0A  
@@ -2667,24 +2667,30 @@
 ;%0A      
+      
 %7D%0A      
 return j
@@ -2677,30 +2677,39 @@
     %7D%0A      
-return
+    %7D%0A         
  jreHiDPI.ge
@@ -2710,20 +2710,61 @@
 DPI.
-get();%0A    %7D
+set(value);%0A        %7D%0A      %7D%0A    %7D%0A    return value;
 %0A  %7D
@@ -3261,89 +3261,41 @@
    i
-f (j
+sJ
 reHiDPI
-.get() == null) %7B%0A      // force init%0A      isJreHiDPIEnabled();%0A    %7D
+Enabled(); // force init
 %0A   

fix concurrency issue in JreHiDpiUtil.isJreHiDPIEnabled()