// 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.

@TestOn('vm')
library webdriver.support.firefox_profile_test;

import 'dart:convert' show base64, Encoding, utf8;
import 'dart:io' as io;

import 'package:archive/archive.dart' show Archive, ArchiveFile, ZipDecoder;
import 'package:test/test.dart';
import 'package:webdriver/async_core.dart';
import 'package:webdriver/support/firefox_profile.dart';

void main() {
  group('Firefox profile', () {
    test('parse and serialize string value with quotes', () {
      const value =
          r'user_pref("extensions.xpiState", "{\"app-global\":{\"{972ce4c6-'
          r'7e08-4474-a285-3208198ce6fd}\":{\"d\":\"/opt/firefox/browser/'
          r'extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}\",\"e\":true,\'
          r'"v\":\"40.0\",\"st\":1439535413000,\"mt\":1438968709000}}}");';
      var option = PrefsOption.parse(value);
      expect(option, isA<StringOption>());
      expect(option.asPrefString, value);
    });

    test('parse and serialize string value with backslash', () {
      const value = r'user_pref("browser.cache.disk.parent_directory", '
          r'"\\\\volume\\web\\cache\\mz");';
      var option = PrefsOption.parse(value);
      expect(option, isA<StringOption>());
      expect(option.asPrefString, value);
    });

    test('parse and serialize integer value', () {
      const value = r'user_pref("browser.cache.frecency_experiment", 3);';
      var option = PrefsOption.parse(value);
      expect(option, isA<IntegerOption>());
      expect(option.asPrefString, value);
    });

    test('parse and serialize negative integer value', () {
      const value = r'user_pref("browser.cache.frecency_experiment", -3);';
      var option = PrefsOption.parse(value);
      expect(option, isA<IntegerOption>());
      expect(option.asPrefString, value);
    });

    test('parse and serialize boolean true', () {
      const value =
          r'user_pref("browser.cache.disk.smart_size.first_run", true);';
      var option = PrefsOption.parse(value);
      expect(option, isA<BooleanOption>());
      expect(option.asPrefString, value);
    });

    test('parse and serialize boolean false', () {
      const value =
          r'user_pref("browser.cache.disk.smart_size.first_run", false);';
      var option = PrefsOption.parse(value);
      expect(option, isA<BooleanOption>());
      expect(option.asPrefString, value);
    });

    test('parse boolean uppercase True', () {
      const value =
          r'user_pref("browser.cache.disk.smart_size.first_run", True);';
      var option = PrefsOption.parse(value);
      expect(option, isA<BooleanOption>());
      expect(option.value, true);
    });

    test('added value should be in prefs', () {
      var profile = FirefoxProfile();
      var option =
          PrefsOption('browser.bookmarks.restore_default_bookmarks', false);

      expect(profile.setOption(option), true);

      expect(
          profile.userPrefs,
          anyElement((PrefsOption e) =>
              e.name == option.name && e.value == option.value));
    });

    test('overriding locked value should be ignored', () {
      var profile = FirefoxProfile();
      var lockedOption = PrefsOption('javascript.enabled', false);
      var lockedOptionOrig =
          profile.prefs.firstWhere((e) => e.name == lockedOption.name);
      expect(lockedOption.value, isNot(lockedOptionOrig.value));

      expect(profile.setOption(lockedOption), false);

      expect(profile.userPrefs, isNot(anyElement(lockedOption)));
      expect(profile.prefs.firstWhere((e) => e.name == lockedOption.name).value,
          lockedOptionOrig.value);
    });

    test('removing locked value should be ignored', () {
      var profile = FirefoxProfile();
      var lockedOption = PrefsOption('javascript.enabled', false);
      var lockedOptionOrig =
          profile.prefs.firstWhere((e) => e.name == lockedOption.name);
      expect(lockedOption.value, isNot(lockedOptionOrig.value));

      expect(profile.removeOption(lockedOption.name), false);

      expect(profile.userPrefs, isNot(anyElement(lockedOption)));
      expect(profile.prefs.firstWhere((e) => e.name == lockedOption.name).value,
          lockedOptionOrig.value);
    });

    test('encode/decode "user.js" in-memory', () {
      var profile = FirefoxProfile();
      profile.setOption(PrefsOption(Capabilities.hasNativeEvents, true));

      var archive = unpackArchiveData(profile.toJson());

      var expectedFiles = ['prefs.js', 'user.js'];
      expect(archive.files.length, greaterThanOrEqualTo(expectedFiles.length));
      expectedFiles.forEach((f) => expect(
          archive.files, anyElement((ArchiveFile f) => f.name == 'prefs.js')));

      var prefs = FirefoxProfile.loadPrefsFile(MockFile(String.fromCharCodes(
          archive.files.firstWhere((f) => f.name == 'user.js').content)));
      expect(
          prefs,
          anyElement((PrefsOption o) =>
              o.name == Capabilities.hasNativeEvents && o.value == true));
    });

    test('encode/decode profile directory from disk', () {
      var profile = FirefoxProfile(
          profileDirectory: io.Directory('test/support/firefox_profile'));
      profile.setOption(PrefsOption(Capabilities.hasNativeEvents, true));

      var archive = unpackArchiveData(profile.toJson());

      var expectedFiles = [
        'prefs.js',
        'user.js',
        'addons.js',
        'webapps/',
        'webapps/webapps.json'
      ];
      expect(archive.files.length, greaterThanOrEqualTo(expectedFiles.length));
      expectedFiles.forEach((f) => expect(
          archive.files, anyElement((ArchiveFile f) => f.name == 'prefs.js')));

      var prefs = FirefoxProfile.loadPrefsFile(MockFile(String.fromCharCodes(
          archive.files.firstWhere((f) => f.name == 'user.js').content)));
      expect(
          prefs,
          anyElement((PrefsOption o) =>
              o.name == Capabilities.hasNativeEvents && o.value == true));
    });
  }, timeout: const Timeout(Duration(minutes: 2)));
}

Archive unpackArchiveData(Map profileData) {
  var zipArchive = base64.decode(profileData['firefox_profile']);
  return ZipDecoder().decodeBytes(zipArchive, verify: true);
}

/// Simulate file for `FirefoxProfile.loadPrefsFile()`
class MockFile implements io.File {
  String content;

  MockFile(this.content);

  @override
  String readAsStringSync({Encoding encoding = utf8}) => content;

  @override
  dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
