import SwiftLintCore

struct UnusedDeclarationRuleExamples {
    static let nonTriggeringExamples = #examples([
        """
        let kConstant = 0
        _ = kConstant
        """,
        """
        enum Change<T> {
          case insert(T)
          case delete(T)
        }

        extension Sequence {
          func deletes<T>() -> [T] where Element == Change<T> {
            return compactMap { operation in
              if case .delete(let value) = operation {
                return value
              } else {
                return nil
              }
            }
          }
        }

        let changes = [Change.insert(0), .delete(0)]
        _ = changes.deletes()
        """,
        """
        struct Item: Codable {}
        struct ResponseModel: Codable {
            let items: [Item]

            enum CodingKeys: String, CodingKey {
                case items = "ResponseItems"
            }
        }

        _ = ResponseModel(items: [Item()]).items
        """,
        """
        class ResponseModel {
            @objc func foo() {
            }
        }
        _ = ResponseModel()
        """,
        """
        public func foo() {}
        """,
        """
        protocol Foo {}

        extension Foo {
            func bar() {}
        }

        struct MyStruct: Foo {}
        MyStruct().bar()
        """,
        """
        import XCTest
        class MyTests: XCTestCase {
            func testExample() {}
        }
        """,
        """
        import XCTest
        open class BestTestCase: XCTestCase {}
        class MyTests: BestTestCase {
            func testExample() {}
        }
        """,
        """
            struct S {
                var i: Int? = nil
                func f() {
                    if let i { print(i) }
                }
            }
            S().f()
        """,
        """
        enum Component {
          case string(StaticString)
          indirect case array([Component])
          indirect case optional(Component?)
        }

        @resultBuilder
        struct ComponentBuilder {
          static func buildBlock(_ components: Component...) -> Component {
            return .array(components)
          }

          static func buildExpression(_ string: StaticString) -> Component {
            return .string(string)
          }

          static func buildOptional(_ component: Component?) -> Component {
            return .optional(component)
          }

          static func buildEither(first component: Component) -> Component {
            return component
          }

          static func buildEither(second component: Component) -> Component {
            return component
          }

          static func buildArray(_ components: [Component]) -> Component {
            return .array(components)
          }

          static func buildLimitedAvailability(_ component: Component) -> Component {
            return component
          }

          static func buildFinalResult(_ component: Component) -> Component {
            return component
          }

          static func buildPartialBlock(first component: Component) -> Component {
            return component
          }

          static func buildPartialBlock(accumulated component: Component, next: Component) -> Component {
            return component
          }
        }

        func acceptComponentBuilder(@ComponentBuilder _ body: () -> Component) {
          print(body())
        }

        acceptComponentBuilder {
          "hello"
        }
        """,
    ]) + platformSpecificNonTriggeringExamples

    static let triggeringExamples = #examples([
        """
        let ↓kConstant = 0
        """,
        """
        struct Item {}
        struct ↓ResponseModel: Codable {
            let ↓items: [Item]

            enum ↓CodingKeys: String {
                case items = "ResponseItems"
            }
        }
        """,
        """
        class ↓ResponseModel {
            func ↓foo() {
            }
        }
        """,
        """
        public func ↓foo() {}
        """.asExample(configuration: ["include_public_and_open": true]),
        """
        protocol Foo {
            func ↓bar1()
        }

        extension Foo {
            func bar1() {}
            func ↓bar2() {}
        }

        struct MyStruct: Foo {}
        _ = MyStruct()
        """,
        """
        import XCTest
        class ↓MyTests: NSObject {
            func ↓testExample() {}
        }
        """,
        """
        enum Component {
          case string(StaticString)
          indirect case array([Component])
          indirect case optional(Component?)
        }

        struct ComponentBuilder {
          func ↓buildExpression(_ string: StaticString) -> Component {
            return .string(string)
          }

          func ↓buildBlock(_ components: Component...) -> Component {
            return .array(components)
          }

          func ↓buildIf(_ value: Component?) -> Component {
            return .optional(value)
          }

          static func ↓buildABear(_ components: Component...) -> Component {
            return .array(components)
          }
        }

        _ = ComponentBuilder()
        """,
        """
        protocol ↓Foo {}
        extension Foo {}
        """,
        """
        class ↓C<T> {}
        extension C<Int> {}
        """,
    ]) + ["actor", "enum", "class", "struct"].map {
        """
        protocol Foo {}
        \($0) ↓FooImpl {}
        extension FooImpl {}
        extension FooImpl: Foo {}
        """.asExample(excludeFromDocumentation: true)
    } + platformSpecificTriggeringExamples

#if os(macOS)
    private static let platformSpecificNonTriggeringExamples = #examples([
        """
        import Cocoa

        @NSApplicationMain
        final class AppDelegate: NSObject, NSApplicationDelegate {
            func applicationWillFinishLaunching(_ notification: Notification) {}
            func applicationWillBecomeActive(_ notification: Notification) {}
        }
        """,
        """
        import Foundation

        public final class Foo: NSObject {
            @IBAction private func foo() {}
        }
        """,
        """
        import Foundation

        public final class Foo: NSObject {
            @objc func foo() {}
        }
        """,
        """
        import Foundation

        public final class Foo: NSObject {
            @IBInspectable private var innerPaddingWidth: Int {
                set { self.backgroundView.innerPaddingWidth = newValue }
                get { return self.backgroundView.innerPaddingWidth }
            }
        }
        """,
        """
        import Foundation

        public final class Foo: NSObject {
            @IBOutlet private var bar: NSObject! {
                set { fatalError() }
                get { fatalError() }
            }

            @IBOutlet private var baz: NSObject! {
                willSet { print("willSet") }
            }

            @IBOutlet private var buzz: NSObject! {
                didSet { print("didSet") }
            }
        }
        """,
    ])

    private static let platformSpecificTriggeringExamples = #examples([
        """
        import Cocoa

        @NSApplicationMain
        final class AppDelegate: NSObject, NSApplicationDelegate {
            func ↓appWillFinishLaunching(_ notification: Notification) {}
            func applicationWillBecomeActive(_ notification: Notification) {}
        }
        """,
        """
        import Cocoa

        final class ↓AppDelegate: NSObject, NSApplicationDelegate {
            func applicationWillFinishLaunching(_ notification: Notification) {}
            func applicationWillBecomeActive(_ notification: Notification) {}
        }
        """,
        """
        import Foundation

        public final class Foo: NSObject {
            @IBOutlet var ↓bar: NSObject!
        }
        """,
        """
        import Foundation

        public final class Foo: NSObject {
            @IBInspectable var ↓bar: String!
        }
        """,
        """
        import Foundation

        final class Foo: NSObject {}
        final class ↓Bar {
            var ↓foo = Foo()
        }
        """,
    ])
#else
    private static let platformSpecificNonTriggeringExamples = [Example]()
    private static let platformSpecificTriggeringExamples = [Example]()
#endif
}
