# Onairos Flutter Package Integration Guide for Swift Apps

This guide provides step-by-step instructions for integrating the Onairos Flutter package into an existing Swift iOS application.

## Prerequisites

- iOS 14.0 or later
- Xcode 12.0 or later
- Flutter 3.0 or later
- CocoaPods 1.10 or later

## Step 1: Project Setup

### 1.1 Update iOS Deployment Target

In your Swift app's Xcode project:

1. Select your project in the navigator
2. Select your target
3. In **General** tab → **Deployment Info**, set **iOS Deployment Target** to **14.0**
4. In **Build Settings** tab, search for "iOS Deployment Target" and set it to **14.0**

### 1.2 Update Podfile

Create or update your `Podfile` with the following configuration:

```ruby
platform :ios, '14.0'
use_frameworks!

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

project 'YourApp', {
  'Debug' => :debug,
  'Profile' => :release,
  'Release' => :release,
}

def flutter_root
  generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
  unless File.exist?(generated_xcode_build_settings_path)
    raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
  end

  File.foreach(generated_xcode_build_settings_path) do |line|
    matches = line.match(/FLUTTER_ROOT\=(.*)/)
    return matches[1].strip if matches
  end
  raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end

require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)

flutter_ios_podfile_setup

target 'YourApp' do
  # Flutter integration
  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
  
  # Your existing pods here
  
end

post_install do |installer|
  flutter_post_install(installer) if defined?(flutter_post_install)
  
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    target.build_configurations.each do |config|
      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '14.0'
      config.build_settings['ENABLE_BITCODE'] = 'NO'
      
      # Fix for GoogleSignIn conflicts
      if target.name == 'GoogleSignIn' || target.name.start_with?('google_sign_in')
        config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '14.0'
      end
      
      # Fix duplicate framework issues
      config.build_settings['CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES'] = 'YES'
      config.build_settings['FRAMEWORK_SEARCH_PATHS'] ||= []
      config.build_settings['FRAMEWORK_SEARCH_PATHS'] << '"$(PODS_CONFIGURATION_BUILD_DIR)"'
    end
  end
end
```

## Step 2: Flutter Module Setup

### 2.1 Create Flutter Module Structure

In your iOS project directory, create the following structure:

```
YourApp/
├── Flutter/
│   ├── Debug.xcconfig
│   ├── Release.xcconfig
│   └── Generated.xcconfig
├── onairos_flutter_module/
│   ├── .ios/
│   ├── lib/
│   ├── pubspec.yaml
│   └── ...
└── YourApp.xcodeproj
```

### 2.2 Create Flutter Configuration Files

Create `Flutter/Debug.xcconfig`:
```
#include? "Pods/Target Support Files/Pods-YourApp/Pods-YourApp.debug.xcconfig"
#include "Generated.xcconfig"
```

Create `Flutter/Release.xcconfig`:
```
#include? "Pods/Target Support Files/Pods-YourApp/Pods-YourApp.release.xcconfig"
#include "Generated.xcconfig"
```

### 2.3 Update Project Build Settings

In Xcode:
1. Select your project → Select your target
2. Go to **Build Settings** tab
3. Search for "Configuration Files"
4. Set:
   - **Debug**: `Flutter/Debug.xcconfig`
   - **Release**: `Flutter/Release.xcconfig`

## Step 3: Xcode Project Configuration

### 3.1 Add Build Phases

1. Select your target in Xcode
2. Go to **Build Phases** tab
3. Click **+** → **New Run Script Phase**
4. Add this script:

```bash
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" embed_and_thin
```

5. Set **Input Files**:
```
$(SRCROOT)/Flutter/App.framework
$(SRCROOT)/Flutter/Flutter.framework
```

6. Set **Output Files**:
```
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/App.framework
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/Flutter.framework
```

### 3.2 Fix Framework Search Paths

In **Build Settings**:
1. Search for "Framework Search Paths"
2. Add:
   - `$(PROJECT_DIR)/Flutter`
   - `$(PODS_CONFIGURATION_BUILD_DIR)`

## Step 4: Swift Integration Code

### 4.1 Create Flutter Engine Manager

Create `FlutterEngineManager.swift`:

```swift
import Flutter
import UIKit

class FlutterEngineManager: NSObject {
    static let shared = FlutterEngineManager()
    
    private var flutterEngine: FlutterEngine?
    
    private override init() {
        super.init()
        setupFlutterEngine()
    }
    
    private func setupFlutterEngine() {
        flutterEngine = FlutterEngine(name: "onairos_engine")
        flutterEngine?.run()
        
        // Register plugins
        GeneratedPluginRegistrant.register(with: flutterEngine!)
    }
    
    func getFlutterEngine() -> FlutterEngine? {
        return flutterEngine
    }
    
    func createFlutterViewController(initialRoute: String? = nil) -> FlutterViewController? {
        guard let engine = flutterEngine else { return nil }
        
        let flutterViewController = FlutterViewController(engine: engine, nibName: nil, bundle: nil)
        if let route = initialRoute {
            flutterViewController.setInitialRoute(route)
        }
        
        return flutterViewController
    }
}
```

### 4.2 Create Onairos Integration Helper

Create `OnairosIntegration.swift`:

```swift
import Flutter
import UIKit

class OnairosIntegration: NSObject {
    private let methodChannel: FlutterMethodChannel
    
    init(engine: FlutterEngine) {
        methodChannel = FlutterMethodChannel(
            name: "com.onairos/integration",
            binaryMessenger: engine.binaryMessenger
        )
        super.init()
        setupMethodChannel()
    }
    
    private func setupMethodChannel() {
        methodChannel.setMethodCallHandler { [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) in
            switch call.method {
            case "showOnairos":
                self?.showOnairosModal(arguments: call.arguments, result: result)
            default:
                result(FlutterMethodNotImplemented)
            }
        }
    }
    
    private func showOnairosModal(arguments: Any?, result: @escaping FlutterResult) {
        DispatchQueue.main.async {
            guard let topViewController = UIApplication.shared.windows.first?.rootViewController else {
                result(FlutterError(code: "NO_CONTROLLER", message: "No root view controller found", details: nil))
                return
            }
            
            let flutterViewController = FlutterEngineManager.shared.createFlutterViewController(initialRoute: "/onairos")
            flutterViewController?.modalPresentationStyle = .pageSheet
            
            if let flutterVC = flutterViewController {
                topViewController.present(flutterVC, animated: true) {
                    result(true)
                }
            } else {
                result(FlutterError(code: "FLUTTER_ERROR", message: "Failed to create Flutter view controller", details: nil))
            }
        }
    }
}
```

### 4.3 Update AppDelegate

Update your `AppDelegate.swift`:

```swift
import UIKit
import Flutter

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    private var onairosIntegration: OnairosIntegration?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // Initialize Flutter Engine
        let flutterEngine = FlutterEngineManager.shared.getFlutterEngine()
        
        // Setup Onairos integration
        if let engine = flutterEngine {
            onairosIntegration = OnairosIntegration(engine: engine)
        }
        
        return true
    }
}
```

## Step 5: Build and Run

### 5.1 Clean and Rebuild

1. Close Xcode
2. In Terminal, navigate to your project directory:

```bash
# Clean everything
rm -rf Pods/
rm -rf .symlinks/
rm Podfile.lock
rm -rf ~/Library/Developer/Xcode/DerivedData/

# Reinstall pods
pod deintegrate
pod cache clean --all
pod install

# Open workspace (not project)
open YourApp.xcworkspace
```

### 5.2 Build Settings Verification

In Xcode, verify these settings:

1. **General** → **Deployment Target**: 14.0
2. **Build Settings** → **Enable Bitcode**: NO
3. **Build Settings** → **Framework Search Paths**: includes `$(PROJECT_DIR)/Flutter`
4. **Build Settings** → **Other Linker Flags**: includes `-ObjC`

## Step 6: Usage in Swift

### 6.1 Using Onairos Button

```swift
import UIKit

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupOnairosButton()
    }
    
    private func setupOnairosButton() {
        let onairosButton = UIButton(type: .system)
        onairosButton.setTitle("Sign in with Onairos", for: .normal)
        onairosButton.backgroundColor = .systemBlue
        onairosButton.setTitleColor(.white, for: .normal)
        onairosButton.layer.cornerRadius = 8
        onairosButton.addTarget(self, action: #selector(onairosButtonTapped), for: .touchUpInside)
        
        // Add button to view with constraints
        view.addSubview(onairosButton)
        onairosButton.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            onairosButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            onairosButton.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            onairosButton.widthAnchor.constraint(equalToConstant: 200),
            onairosButton.heightAnchor.constraint(equalToConstant: 50)
        ])
    }
    
    @objc private func onairosButtonTapped() {
        guard let engine = FlutterEngineManager.shared.getFlutterEngine() else { return }
        
        let methodChannel = FlutterMethodChannel(
            name: "com.onairos/integration",
            binaryMessenger: engine.binaryMessenger
        )
        
        methodChannel.invokeMethod("showOnairos", arguments: [
            "appName": "YourApp",
            "buttonType": "normal"
        ]) { result in
            print("Onairos result: \(result)")
        }
    }
}
```

## Troubleshooting

### Common Issues:

1. **GeneratedPluginRegistrant.h not found**:
   - Run `flutter pub get` in your Flutter module
   - Clean and rebuild the project

2. **Multiple commands produce framework**:
   - Set `use_frameworks!` in Podfile
   - Add `config.build_settings['CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES'] = 'YES'` in post_install

3. **GoogleSignIn version conflicts**:
   - Ensure all GoogleSignIn dependencies use version 8.0+
   - Run `pod update GoogleSignIn`

4. **Deployment target issues**:
   - Set deployment target to 14.0 in all configurations
   - Update both project and target settings

### Clean Build Commands:

```bash
# Complete clean
rm -rf Pods/ .symlinks/ Podfile.lock
rm -rf ~/Library/Developer/Xcode/DerivedData/
pod cache clean --all
pod deintegrate
pod install

# Flutter clean
flutter clean
flutter pub get

# Xcode clean
# Product → Clean Build Folder in Xcode
```

This integration guide should resolve all the conflicts and provide a working setup for your Swift app to use the Onairos Flutter package.
