//
//  InputFile.swift
//  FastCoster
//
//  Created by Michael Pivato on 3/5/2024.
//

import Foundation

struct NodeInfo: Codable {
    var name: String;
    var outputFiles: [String]
    var configuration: NodeConfiguration
}

// Need to check if enums with data actually works with json serialisation/deserialisation, otherwise
// can look into binary serialisation/deserialisation instead
enum NodeConfiguration: Codable {
    case FileNode
    case MoveMoneyNode(MoveMoneyNode)
    case MergeNode(MergeNode)
    case DeriveNode(DeriveNode)
}

enum MoveMoneyAmoutType: String, Codable {
    case Percent, Amount
}

struct MoveMoneyRule: Codable {
    let fromAccout: String
    let fromCC: String
    let toAccount: String
    let toCC: String
    let value: Double
    let type: MoveMoneyAmoutType
}

struct MoveMoneyNode: Codable {
    var departmentsPath: String
    var accountsPath: String
    var glPath: String
    var rules: [MoveMoneyRule]
}

enum JoinType: Codable {
    case Left, Inner, Right
}

struct MergeJoin: Codable {
    var type: JoinType
    var leftColumnName: String
    var rightColumnName: String
}

struct MergeNode: Codable {
    var inputFiles: [String]
    var joins: [MergeJoin]
}

enum DeriveColumnType: Codable {
    case Column(String)
    case Constant(String)
}

struct MapOperation: Codable {
    var mappedValue: String
}

enum DatePart: Codable {
    case Year, Month, Week, Day, Hour, Minute, Secod
}

enum SplitType: Codable {
    case DateTime(String, DatePart)
    case Numeric(String, Int)
}

enum MatchComparisonType: Codable {
    case Equal, GreaterThan, LessThan
}

enum DeriveOperation: Codable {
    case Concat([DeriveColumnType])
    case Add([DeriveColumnType])
    case Multiply([DeriveColumnType])
    case Subtract(DeriveColumnType, DeriveColumnType)
    case Divide(DeriveColumnType, DeriveColumnType)
    case Map(String, [MapOperation])
    case Split(String, SplitType)
}

struct DeriveFilter: Codable {
    var columnName: String
    var comparator: MatchComparisonType
    var matchValue: String
}

struct DeriveRule: Codable {
    // Should this actually be  an array though? It think it's fine?
    var operations: [DeriveOperation]
    // Filter to only specific values if required, if empty every value is considered a match
    var filters: [DeriveFilter]
}

struct DeriveNode: Codable {
    var rules: [DeriveRule]
}


// Example json serialisation
func tryJson() {
    do {
        let json = try JSONEncoder().encode(NodeInfo(name: "", outputFiles: [], configuration: NodeConfiguration.FileNode))
        let decoded = try JSONDecoder().decode(NodeInfo.self, from: json)
    }catch {
        
    }
}
