/*
 * Copyright (c) 2025
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

import 'dart:io';

import 'package:flutter/services.dart';
import 'package:splash_video/utils.dart';

/// Base class for all video source types
sealed class Source {
  /// Validates and prepares the source for use
  void setSource();
}

/// Represents a video asset bundled with the application
final class AssetSource extends Source {
  /// The asset path relative to the project root
  final String path;

  /// Creates an asset source with the given [path]
  /// 
  /// Example: `AssetSource('assets/videos/splash.mp4')`
  AssetSource(this.path);

  @override
  Future<void> setSource() async {}
}

/// Represents a video file on the device's file system
final class DeviceFileSource extends Source {
  /// The absolute path to the video file on the device
  final String path;

  /// The File object created from the path
  late final File file;

  /// Creates a device file source with the given [path]
  /// 
  /// Example: `DeviceFileSource('/path/to/video.mp4')`
  DeviceFileSource(this.path);

  @override
  Future<void> setSource() async {
    file = File(path);
  }
}

/// Represents a video available via network URL
final class NetworkFileSource extends Source {
  /// The URL string pointing to the video file
  final String path;
  Uri? _url;

  /// The parsed URI object
  Uri? get url => _url;

  /// Creates a network file source with the given [path]
  /// 
  /// The path should be a valid URL string.
  /// Example: `NetworkFileSource('https://example.com/video.mp4')`
  NetworkFileSource(this.path) {
    setSource();
  }

  @override
  void setSource() {
    _url = Uri.tryParse(path);
    if (_url == null) {
      throw SplashVideoException(message: 'Unable to parse URI: $path');
    }
  }
}

/// Represents a video loaded from raw bytes in memory
final class BytesSource extends Source {
  /// The raw video data as bytes
  final Uint8List bytes;

  /// Creates a bytes source with the given [bytes]
  /// 
  /// This is useful for videos loaded from memory or custom sources
  BytesSource(this.bytes);

  @override
  void setSource() {}
}
