#
# CMakeNodeTools.txt
#
# Copyright (C) 2022 by Posit Software, PBC
#
# This program is licensed to you under the terms of version 3 of the
# GNU Affero General Public License. This program is distributed WITHOUT
# ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
# AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
# 
#

# include guard
if(RSTUDIO_CMAKE_NODE_TOOLS_INCLUDED)
   return()
endif()
set(RSTUDIO_CMAKE_NODE_TOOLS_INCLUDED YES)

# set the node version
if(NOT DEFINED RSTUDIO_NODE_VERSION)
   set(RSTUDIO_NODE_VERSION "22.22.2")
endif()
if(DEFINED ENV{RSTUDIO_NODE_VERSION})
   set(RSTUDIO_NODE_VERSION $ENV{RSTUDIO_NODE_VERSION})
endif()

# set cmake env vars for node (NODEJS) and node tools, like YARN, and NPM

# resolve the primary git worktree so a secondary worktree (whose downloaded
# deps are gitignored and hence empty) can borrow the primary checkout's node
include("${CMAKE_CURRENT_LIST_DIR}/../../cmake/git-worktree.cmake")
set(RSTUDIO_WORKTREE_NODE_DIR "")
if(RSTUDIO_GIT_MAIN_WORKTREE)
   set(RSTUDIO_WORKTREE_NODE_DIR "${RSTUDIO_GIT_MAIN_WORKTREE}/dependencies/common/node/${RSTUDIO_NODE_VERSION}")
endif()

if(APPLE AND UNAME_M STREQUAL arm64)

   # make sure we're using arm64 binaries of node / npm for arm64 builds; search
   # this checkout first, then the primary worktree. Use find_program (like the
   # else branch) so a missing path leaves the var empty and trips the clear
   # "not found" error below rather than passing a bogus path on to first use.
   set(RSTUDIO_NODE_ARM64_PATHS
      "${CMAKE_CURRENT_LIST_DIR}/../../dependencies/common/node/${RSTUDIO_NODE_VERSION}-arm64")
   if(RSTUDIO_WORKTREE_NODE_DIR)
      list(APPEND RSTUDIO_NODE_ARM64_PATHS "${RSTUDIO_WORKTREE_NODE_DIR}-arm64")
   endif()

   find_program(NODEJS NAMES node NO_DEFAULT_PATH PATH_SUFFIXES "bin" PATHS ${RSTUDIO_NODE_ARM64_PATHS})
   find_program(NPM    NAMES npm  NO_DEFAULT_PATH PATH_SUFFIXES "bin" PATHS ${RSTUDIO_NODE_ARM64_PATHS})
   find_program(NPX    NAMES npx  NO_DEFAULT_PATH PATH_SUFFIXES "bin" PATHS ${RSTUDIO_NODE_ARM64_PATHS})

else()

   # Detect node.js, npm, and npx; use versions supplied by the dependency scripts
   find_program(NODEJS
      NAMES node
      NO_DEFAULT_PATH PATH_SUFFIXES "bin"
      PATHS "${RSTUDIO_TOOLS_ROOT}/dependencies/common/node/${RSTUDIO_NODE_VERSION}"
      "/opt/rstudio-tools/dependencies/common/node/${RSTUDIO_NODE_VERSION}"
      "c:/rstudio-tools/dependencies/common/node/${RSTUDIO_NODE_VERSION}"
      "${CMAKE_CURRENT_LIST_DIR}/../../dependencies/common/node/${RSTUDIO_NODE_VERSION}"
      "${RSTUDIO_WORKTREE_NODE_DIR}")

   find_program(NPM
      NAMES npm
      PATH_SUFFIXES "bin"
      NO_DEFAULT_PATH 
      PATHS "${RSTUDIO_TOOLS_ROOT}/dependencies/common/node/${RSTUDIO_NODE_VERSION}"
      "/opt/rstudio-tools/dependencies/common/node/${RSTUDIO_NODE_VERSION}"
      "c:/rstudio-tools/dependencies/common/node/${RSTUDIO_NODE_VERSION}"
      "${CMAKE_CURRENT_LIST_DIR}/../../dependencies/common/node/${RSTUDIO_NODE_VERSION}"
      "${RSTUDIO_WORKTREE_NODE_DIR}")

   find_program(NPX
      NAMES npx
      PATH_SUFFIXES "bin"
      NO_DEFAULT_PATH 
      PATHS "${RSTUDIO_TOOLS_ROOT}/dependencies/common/node/${RSTUDIO_NODE_VERSION}"
      "/opt/rstudio-tools/dependencies/common/node/${RSTUDIO_NODE_VERSION}"
      "c:/rstudio-tools/dependencies/common/node/${RSTUDIO_NODE_VERSION}"
      "${CMAKE_CURRENT_LIST_DIR}/../../dependencies/common/node/${RSTUDIO_NODE_VERSION}"
      "${RSTUDIO_WORKTREE_NODE_DIR}")

endif()
   
if(NODEJS)
   message(STATUS "Using node.js: ${NODEJS}")
else()
   message(FATAL_ERROR "node.js not found (required)")
endif()
   
if(NPM)
   message(STATUS "Using npm: ${NPM}")
else()
   message(FATAL_ERROR "npm not found (required for rsw-homepage)")
endif()

if(NPX)
   message(STATUS "Using npx: ${NPX}")
else()
   message(STATUS "npx not found (required for Electron)")
endif()

get_filename_component(NODEJS_PATH ${NODEJS} DIRECTORY CACHE)

# yarn
if(UNIX)

   find_program(YARN
      NAMES yarn
      NO_DEFAULT_PATH
      PATHS "$ENV{HOME}/.yarn/bin")

elseif(WIN32)

   find_program(YARN
      NAMES yarn
      NO_DEFAULT_PATH
      PATHS "${NODEJS_PATH}")

endif()

if (NOT YARN)
   find_program(YARN NAMES yarn)
endif()

if(YARN)
   message(STATUS "Using yarn: ${YARN}")
else()
   message(STATUS "yarn not found (required for Electron)")
   set(YARN yarn)
endif()

# cache variables
set(NODEJS "${NODEJS}" CACHE INTERNAL "")
set(YARN "${YARN}" CACHE INTERNAL "")
set(NPM "${NPM}" CACHE INTERNAL "")
set(NPX "${NPX}" CACHE INTERNAL "")

# create paths from programs
get_filename_component(YARN_PATH ${YARN} DIRECTORY CACHE)
get_filename_component(NPM_PATH ${NPM} DIRECTORY CACHE)
get_filename_component(NPX_PATH ${NPX} DIRECTORY CACHE)

