AccentPomodoro / Accent Pomodoro / MenuBarColorChanger.swift
MenuBarColorChanger.swift
Raw
//
//  MenuBarColorChanger.swift
//  Accent Pomodoro
//
//  Created by Luke Jenquin on 11/26/21.
//

import Foundation
import Cocoa
import SwiftUI

final class MenuBarColorChanger {
    @ObservedObject var userSelections: userSelectionsModel
    private var wallpaper: String?
    private var firstChange: Bool = true
    private var originalWallpapers: [NSURL?]
    private var changedMenuBar: Bool = false
    
    init(currentUserSelections: userSelectionsModel) {
        userSelections = currentUserSelections
        originalWallpapers = [NSURL?](repeating: nil, count: NSScreen.screens.count)
    }
    
    func changeMenuColor(colorChange: Int) {
        let screens: [NSScreen] = NSScreen.screens

        guard !screens.isEmpty else {
            return
        }
        let changeMenuBarColor = (userSelections.changeFocusMenuBar && colorChange == 0) || (userSelections.changeRelaxMenuBar && colorChange == 1)
        for (index, screen) in screens.enumerated() {
            if (firstChange) {
                originalWallpapers[index] = NSWorkspace.shared.desktopImageURL(for: screen)! as NSURL
            }
            if ( changeMenuBarColor ) {
                guard let adjustedWallpaper = createWallpaper(screen: screen, colorChange: colorChange), let data = adjustedWallpaper.jpgData else {
                    continue
                }

                setWallpaper(screen: screen, wallpaper: data, colorChange: colorChange)
                changedMenuBar = true
            }
        }
        if ( !changeMenuBarColor && !changedMenuBar) {
            resetWallpapers()
            changedMenuBar = false
        }
        firstChange = false
    }
    
    
    func createWallpaper(screen: NSScreen, colorChange: Int) -> NSImage? {
        guard let wallpaper = loadWallpaperImage(wallpaper: wallpaper, screen: screen) else {
            return nil
        }
        var color = NSColor(userSelections.focusColor)
        if (colorChange == 1) {
            color = NSColor(userSelections.relaxColor)
        }

        guard let resizedWallpaper = wallpaper.crop(size: screen.size) else {
            return nil
        }

        guard let topImage = createSolidImage(color: color, width: screen.size.width, height: screen.menuBarHeight) else {
            return nil
        }

        return combineImages(baseImage: resizedWallpaper, addedImage: topImage)
    }
    
    func loadWallpaperImage(wallpaper: String?, screen: NSScreen) -> NSImage? {
        if let path = wallpaper {
            guard let wallpaper = NSImage(contentsOfFile: path) else {
                return nil
            }

            return wallpaper
        }

        guard let path = NSWorkspace.shared.desktopImageURL(for: screen), let wallpaper = NSImage(contentsOf: path) else {
            return nil
        }

        return wallpaper
    }
    
    func setWallpaper(screen: NSScreen, wallpaper: Data, colorChange: Int) {
        guard let supportFiles = try? Folder.library?.subfolder(at: "Application Support"), let workingDirectory = try? supportFiles.createSubfolderIfNeeded(at: "AccentPomodoro") else {
            return
        }

        do {
            let generatedWallpaperFile = workingDirectory.url.appendingPathComponent("/wallpaper-screen-adjusted-\(screen.hashValue)-colorChange\(colorChange).jpg")
            try? FileManager.default.removeItem(at: generatedWallpaperFile)

            try wallpaper.write(to: generatedWallpaperFile)

            try NSWorkspace.shared.setDesktopImageURL(generatedWallpaperFile, for: screen, options: [:])
        } catch {
        }
    }
    
    func resetWallpapers() {
        let screens: [NSScreen] = NSScreen.screens

        guard !screens.isEmpty else {
            return
        }

        for (index, screen) in screens.enumerated() {
            do {
                try NSWorkspace.shared.setDesktopImageURL(originalWallpapers[index]! as URL, for: screen, options: [:])
            } catch {
            }
        }
    }
}