// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

library webdriver.sync_core;

import 'dart:collection' show UnmodifiableMapView;

import 'package:webdriver/src/sync/capabilities.dart' show Capabilities;
import 'package:webdriver/src/sync/web_driver.dart' show WebDriver;

import 'package:webdriver/src/sync/command_processor.dart';
import 'package:webdriver/src/sync/json_wire_spec/response_processor.dart';
import 'package:webdriver/src/sync/json_wire_spec/web_driver.dart' as jwire;
import 'package:webdriver/src/sync/w3c_spec/response_processor.dart';
import 'package:webdriver/src/sync/w3c_spec/web_driver.dart' as w3c;

export 'package:webdriver/src/sync/alert.dart';
export 'package:webdriver/src/sync/capabilities.dart';
export 'package:webdriver/src/sync/command_event.dart';
export 'package:webdriver/src/sync/command_processor.dart';
export 'package:webdriver/src/sync/common.dart';
export 'package:webdriver/src/sync/common_spec/cookies.dart';
export 'package:webdriver/src/sync/navigation.dart';
export 'package:webdriver/src/sync/exception.dart';
export 'package:webdriver/src/sync/json_wire_spec/keyboard.dart';
export 'package:webdriver/src/sync/json_wire_spec/logs.dart';
export 'package:webdriver/src/sync/json_wire_spec/mouse.dart';
export 'package:webdriver/src/sync/timeouts.dart';
export 'package:webdriver/src/sync/target_locator.dart';
export 'package:webdriver/src/sync/web_driver.dart';
export 'package:webdriver/src/sync/web_element.dart';
export 'package:webdriver/src/sync/window.dart';

final Uri defaultUri = Uri.parse('http://127.0.0.1:4444/wd/hub/');

/// Defines the WebDriver spec to use. Auto = try to infer the spec based on
/// the response during session creation.
enum WebDriverSpec { Auto, JsonWire, W3c }

//TODO(staats): infer spec during WebDriver creation.
WebDriver createDriver(
    {Uri uri,
    Map<String, dynamic> desired,
    WebDriverSpec spec = WebDriverSpec.JsonWire}) {
  if (uri == null) {
    uri = defaultUri;
  }

  if (desired == null) {
    desired = Capabilities.empty;
  }

  switch (spec) {
    case WebDriverSpec.JsonWire:
      final processor =
          new SyncHttpCommandProcessor(processor: processJsonWireResponse);
      final response = processor.post(
          uri.resolve('session'), {'desiredCapabilities': desired},
          value: false) as Map<String, dynamic>;
      return new jwire.JsonWireWebDriver(processor, uri, response['sessionId'],
          new UnmodifiableMapView(response['value'] as Map<String, dynamic>));
    case WebDriverSpec.W3c:
      final processor =
          new SyncHttpCommandProcessor(processor: processW3cResponse);
      final response = processor.post(
          uri.resolve('session'), {'desiredCapabilities': desired},
          value: true) as Map<String, dynamic>;
      return new w3c.W3cWebDriver(processor, uri, response['sessionId'],
          new UnmodifiableMapView(response['value'] as Map<String, dynamic>));
    case WebDriverSpec.Auto:
      throw 'Not yet supported!';
    default:
      throw 'Not yet supported!'; // Impossible.
  }
}

WebDriver fromExistingSession(String sessionId,
    {Uri uri, WebDriverSpec spec = WebDriverSpec.JsonWire}) {
  if (uri == null) {
    uri = defaultUri;
  }

  switch (spec) {
    case WebDriverSpec.JsonWire:
      final processor =
          new SyncHttpCommandProcessor(processor: processJsonWireResponse);
      final response = processor.get(uri.resolve('session/$sessionId'))
          as Map<String, dynamic>;
      return new jwire.JsonWireWebDriver(
          processor, uri, sessionId, new UnmodifiableMapView(response));
    case WebDriverSpec.W3c:
      final processor =
          new SyncHttpCommandProcessor(processor: processW3cResponse);
      final response = processor.get(uri.resolve('session/$sessionId'))
          as Map<String, dynamic>;
      return new w3c.W3cWebDriver(
          processor, uri, sessionId, new UnmodifiableMapView(response));
    case WebDriverSpec.Auto:
      throw 'Not yet supported!';
    default:
      throw 'Not yet supported!'; // Impossible.
  }
}
