using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Parser;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NzbDrone.Core.Parser.Model;
using System;
using NzbDrone.Common.Http;
using Moq;
using static NzbDrone.Core.Parser.FingerprintingService;
using NzbDrone.Test.Common;
using System.Net;

namespace NzbDrone.Core.Test.ParserTests
{
    [TestFixture]
    public class FingerprintingServiceFixture : CoreTest<FingerprintingService>
    {

        [Test]
        public void should_parse_fpcalc_json()
        {
            var json = "{\"duration\": 229.29, \"fingerprint\": \"AQADtFMURlEURcgP6cwRD43Y4Ptw9FowncWPWkf6GB9-JYdP9OgJHw8u4Apw4SsOHMdxHAfwHIfYET_0HiZ55MfxNCm8Hj-mRM8KLlXwIzqS-Que_Cg7NEseE_2j4DUjJBOvI08UNNUufEd5NM-OHzmSUZsO58er7nhUeN6EK3HYwhe0H-fxXEFzlOSHJwpj3MevID7kHyqVqBH6zEI6GzmSs4HTDz4j9DjxKHDvpLiOH7l4iFUWRXiiqtCJmMqNPmiAZEyY5AgTLclxmSWuwJ-O33jz4KdwHt-PsDHRjBNyCQ_-KcGPhoePsJNyiJOiI-5VPKMj_McvfNQRUkyiImEzAv2Ckxb-RUJ-CVpGhMYnB5em4scvHFeuoU7DwHugT8fRecPVpMF5_Cb8jNvw4n_wJ6iV4xcSHuFxKcfTBhVF5uiPA6OSoWQP5x_6BX-5YDoaJT_OLA3e0Ifr4D2SH2EYB-WShLiE6plg5U2G6jlOSgy-G8-Rk0XD7yiP4DyPfcejiQ2aH9WVHKeOJ5eQP9CeKEfD44zw45kj_NAQJmIWfMTPCJF048IPPTtcB_GP_2ieFydyxYXGvUgffIO1D96SHW10vEeYI9mNR-qLhnpwfYHz49KR8ijnol58pDGLKWuF4wvKTUGjrE-Q79COdFyI8Aze4C70LMP24-YKJLtSeCHqajJ6e2g0qsdzBd94RNdxHY80oomYocdB5hNiUrGIVtrhJ0f4CY-Y48yOF5rFI93sgNF2hNRhTSk65odGaUhJClc5ArOGdi8-oz_SzaqQ3MKV63DkGX8NT07wVcdf5MmO5Av8C9dOONGIS_mRS7gO8fjhLNMFbQqq4zF0jRPir2j2Y9_xH5Z-_EFiHWE-oaePh8JN3CsaiYgkGvrR_OgVaI2iHv_gTLsQaTeuZ8K5HUdMCWUlHpLIIFyO8TiNO2nQOHzwLkfYQg2RHxXlUfDxHX-MO9Pxwc8J90JSEzmDJk-Ji0cpZanw44mOWpKEkkHDsUFkZsfNaJCOqDvK_fg-9NHx5UHtFGEOPUeu47hw4dzwH22Nc9pgK8dZhJ-h8wipwyS8Dw8cZ0evC8kZJcgrHT22jsfhH_QCv4jMHNp25NLx6Hh4tEtaePzgcNHxDOkYQ3tCxBsvPFKOfyzCB-L5IHyCpzhFHo9zvMeP5vrQbdzwK8N_hFG6F0mdo2GOJ4yxM0bJRFaGH3WyHUdzHWWe4uoH8hWS8EGOGuUSBZ-E6w7sZsKpIId-IzyDptLxhD76GpfxNDHSkdCTS0JMFS-8Rh6e48c6Hv2O8CG05MinRcUX9A0cKoSv4Ts8KbSQbCXyDDeDZ_mKUrwHP8tRi8d94UcX3ImMLzq8o3-DnFXwHG2UJ_Au6FlwNLgOXU_xakKv4zp8VMeN_vBz9OCbQzsFP7h8PB96Df8llNJSWI8KfVkqZMcPaw5ePEgf6HKQjj2YTRmOxslyTJ-K_kj3Qj9M6TjCM33QixGcX8PzHNfxDOfhMx2SHflz_Dr-K6hSKVLQ7MSjII-UQ9fQ53Bi6ahMoz5jNA304xDz7RjTI08eXKeChzmeDeUJfw7OEPVGnB_yoz_M6sZj8MOfHE5wXKLhT0V-MMhjlDv0C-mP_jgt4cxRMgoLSz5GkUZ-3MFTPHCpB-W2EheX43iWeUgfDhdJPAsR_oKWmDGeJRMRoyea3fhyVA6RjsuCCxdDiD-2fsizC5eSp_CPh4UnP5gU6sOpL7g3ocyCSDn0I7-L4znKBg3uKDmeW8Nzsriqg5eMHk33Cn9Q_0hPQtMX4oqOfMedHI-I2mPwd0PeQ8yHsByu4zqHPkfzo4-OtE6R7Dq-5fg3o-kuoVU84VGLIDkNqzEFNt1x7RvOHO7wf8hznDz0KA6F6-g1uE2OPseFvKh-9MGp4we7LLmIhxE1JHeDcLyOUD8uDTozND_apQvyiQ9yQcoRxisuBxeVDd-LRrGO-0xRKwuPh4ivHP8GUQ_ig87RN0czSkf0xEMNcRzxw8elHKIikcKlB5bGY-J9PImJ64K4PCDD7rh8_Ogvo5kOmU0RnjmcC2na9LiGbpKhC48RJvo2hI-HD80sVONx58nQ49CfLtCj59CTBz8eDZ4O7fHwBw-hPhJ0HhqlU0h9XB9qKsh_fNmRiTz-qPido6l3lB0X_DiS90QOOxdxbwJ94XqjwmKyHBeLHzfyH1MuaM9xibgeCe2O5gv-QzUz5NtRay8s7Tj6E1cSHH2eIa0tJB9OBVXa4g9-1M6DOsPTo3wwJQo3PA_4TMh_JJEPb4OzHSUTbcIvPCHcI4-gE7mOp8RxRyX6ySvM2EbJbhEeHVeKZOkR_hJKKTvM_SiPu9FhOUes6kJySTneozfO0HiObSy-7AXDp8gbJMd-4TmebB9KiYKfHNWPG8c9JGvUI5Tz4Xle3FEkhD-01DFy4gnKoOTxw23wOfjRjNKPZNp2Io8OpxmuJsW-7DgvoXYenEEtCT2aKDfIMDv-TEJ0JMtxoZk04Uqi4Ic_HLGP5JLRC80_XFJC9JnwjpNRjTueRSuS_4h4NIfzBl00E5-mo3ckNB-FPIE-5BlO9UL5Dudx5vikFB5DF-FKI7myxPjj4Yzw7OjRxOHxB8f3o9wO34V__IR5UkSf7LiOPhLSL-DR4MKlo5zwr8LFAf8h_oBtVTj8GIcAAYgB4YwSDACBiFBMPPGctY6a6pAAxighhEjKAAaBNsgIIAAQRgFFHCBGIACQIBJAoAAADCKiCDLSCCABQYQQwIwEigkArKGII0OUQEwAogBRoCCHCCKQAEcEkQYQYoQSigDjCBMCIUCJIUQJQQRRiDAAHSEKEOCCEAAgDRQBxDEgkBEGEAQQFkIIIAQhAgnBAFTAQIEAQYgxYwBClAkEACMEAEAAMQgISAxCgiiCACESIWQAUWYQBoBDBhBGgBBAMSMkYogAIwjwBCMkACLCCASEIMARg4QCBCAijCYAKweEAkAJYRgSAkDjjBCMQgioMIYBQIgDQhkBGiKEQAeBFAQAZoACBgFKFAEAOQMAEIQYgICShChGCCDKESSYoEIQAIRiFkAAgQJMCWMYRUAIgAQAigFEgFDEEAEwEAYQaQw0BgEHADDWGSCAWEgIBQQxBghmjBQCCEqMA0YpQIwAwgDjHFBECiWUEQYxohABRAhAjAUCESUARgRQYgAARggKMAVOAEIEc4gyJ4ABABCCjGMIKAIAEQIAIAwChAEgAGEAGAeIUMZY4QghSBhADSCCGiKNlAQoogAChjCDEAEEWEIRA0QohoQAQCkECEGQEQIEMUwYgIgBABgECECCKEQAAkIgYZARBgmADDNKIEAEoAgAAAQDBAgCHJCAEGG0QkQAaZgAAkpAkBAGImAgIYI5AoQAAiBBiCDMASGIYQAoB4QgCAlBIHFIICaAIM4aJawAxFIBDAFGGEA5AUQAgZhCTgJBgEKAACEMI4gwRRwQDAEEIQFEIaKIQYQBgYgBCjiGgAHEUQGYAIwwQASSylCjgJKMI8AIhIAAgAQwBBChhCIKAyOAVIIZAYBBihIIiBAACKMUUhI6JYAAigBADFAiAGBAhoZApRRQwABAiCCAGGcAQUIaBQBhgjBDACEEWSEsYAQYBIAVAACCmDAhEUAEEEQJhQA\"}";

            var result = Subject.ParseFpcalcJsonOutput(json);

            result.Duration.Should().Be(229.29);
            result.Fingerprint.Should().Be("AQADtFMURlEURcgP6cwRD43Y4Ptw9FowncWPWkf6GB9-JYdP9OgJHw8u4Apw4SsOHMdxHAfwHIfYET_0HiZ55MfxNCm8Hj-mRM8KLlXwIzqS-Que_Cg7NEseE_2j4DUjJBOvI08UNNUufEd5NM-OHzmSUZsO58er7nhUeN6EK3HYwhe0H-fxXEFzlOSHJwpj3MevID7kHyqVqBH6zEI6GzmSs4HTDz4j9DjxKHDvpLiOH7l4iFUWRXiiqtCJmMqNPmiAZEyY5AgTLclxmSWuwJ-O33jz4KdwHt-PsDHRjBNyCQ_-KcGPhoePsJNyiJOiI-5VPKMj_McvfNQRUkyiImEzAv2Ckxb-RUJ-CVpGhMYnB5em4scvHFeuoU7DwHugT8fRecPVpMF5_Cb8jNvw4n_wJ6iV4xcSHuFxKcfTBhVF5uiPA6OSoWQP5x_6BX-5YDoaJT_OLA3e0Ifr4D2SH2EYB-WShLiE6plg5U2G6jlOSgy-G8-Rk0XD7yiP4DyPfcejiQ2aH9WVHKeOJ5eQP9CeKEfD44zw45kj_NAQJmIWfMTPCJF048IPPTtcB_GP_2ieFydyxYXGvUgffIO1D96SHW10vEeYI9mNR-qLhnpwfYHz49KR8ijnol58pDGLKWuF4wvKTUGjrE-Q79COdFyI8Aze4C70LMP24-YKJLtSeCHqajJ6e2g0qsdzBd94RNdxHY80oomYocdB5hNiUrGIVtrhJ0f4CY-Y48yOF5rFI93sgNF2hNRhTSk65odGaUhJClc5ArOGdi8-oz_SzaqQ3MKV63DkGX8NT07wVcdf5MmO5Av8C9dOONGIS_mRS7gO8fjhLNMFbQqq4zF0jRPir2j2Y9_xH5Z-_EFiHWE-oaePh8JN3CsaiYgkGvrR_OgVaI2iHv_gTLsQaTeuZ8K5HUdMCWUlHpLIIFyO8TiNO2nQOHzwLkfYQg2RHxXlUfDxHX-MO9Pxwc8J90JSEzmDJk-Ji0cpZanw44mOWpKEkkHDsUFkZsfNaJCOqDvK_fg-9NHx5UHtFGEOPUeu47hw4dzwH22Nc9pgK8dZhJ-h8wipwyS8Dw8cZ0evC8kZJcgrHT22jsfhH_QCv4jMHNp25NLx6Hh4tEtaePzgcNHxDOkYQ3tCxBsvPFKOfyzCB-L5IHyCpzhFHo9zvMeP5vrQbdzwK8N_hFG6F0mdo2GOJ4yxM0bJRFaGH3WyHUdzHWWe4uoH8hWS8EGOGuUSBZ-E6w7sZsKpIId-IzyDptLxhD76GpfxNDHSkdCTS0JMFS-8Rh6e48c6Hv2O8CG05MinRcUX9A0cKoSv4Ts8KbSQbCXyDDeDZ_mKUrwHP8tRi8d94UcX3ImMLzq8o3-DnFXwHG2UJ_Au6FlwNLgOXU_xakKv4zp8VMeN_vBz9OCbQzsFP7h8PB96Df8llNJSWI8KfVkqZMcPaw5ePEgf6HKQjj2YTRmOxslyTJ-K_kj3Qj9M6TjCM33QixGcX8PzHNfxDOfhMx2SHflz_Dr-K6hSKVLQ7MSjII-UQ9fQ53Bi6ahMoz5jNA304xDz7RjTI08eXKeChzmeDeUJfw7OEPVGnB_yoz_M6sZj8MOfHE5wXKLhT0V-MMhjlDv0C-mP_jgt4cxRMgoLSz5GkUZ-3MFTPHCpB-W2EheX43iWeUgfDhdJPAsR_oKWmDGeJRMRoyea3fhyVA6RjsuCCxdDiD-2fsizC5eSp_CPh4UnP5gU6sOpL7g3ocyCSDn0I7-L4znKBg3uKDmeW8Nzsriqg5eMHk33Cn9Q_0hPQtMX4oqOfMedHI-I2mPwd0PeQ8yHsByu4zqHPkfzo4-OtE6R7Dq-5fg3o-kuoVU84VGLIDkNqzEFNt1x7RvOHO7wf8hznDz0KA6F6-g1uE2OPseFvKh-9MGp4we7LLmIhxE1JHeDcLyOUD8uDTozND_apQvyiQ9yQcoRxisuBxeVDd-LRrGO-0xRKwuPh4ivHP8GUQ_ig87RN0czSkf0xEMNcRzxw8elHKIikcKlB5bGY-J9PImJ64K4PCDD7rh8_Ogvo5kOmU0RnjmcC2na9LiGbpKhC48RJvo2hI-HD80sVONx58nQ49CfLtCj59CTBz8eDZ4O7fHwBw-hPhJ0HhqlU0h9XB9qKsh_fNmRiTz-qPido6l3lB0X_DiS90QOOxdxbwJ94XqjwmKyHBeLHzfyH1MuaM9xibgeCe2O5gv-QzUz5NtRay8s7Tj6E1cSHH2eIa0tJB9OBVXa4g9-1M6DOsPTo3wwJQo3PA_4TMh_JJEPb4OzHSUTbcIvPCHcI4-gE7mOp8RxRyX6ySvM2EbJbhEeHVeKZOkR_hJKKTvM_SiPu9FhOUes6kJySTneozfO0HiObSy-7AXDp8gbJMd-4TmebB9KiYKfHNWPG8c9JGvUI5Tz4Xle3FEkhD-01DFy4gnKoOTxw23wOfjRjNKPZNp2Io8OpxmuJsW-7DgvoXYenEEtCT2aKDfIMDv-TEJ0JMtxoZk04Uqi4Ic_HLGP5JLRC80_XFJC9JnwjpNRjTueRSuS_4h4NIfzBl00E5-mo3ckNB-FPIE-5BlO9UL5Dudx5vikFB5DF-FKI7myxPjj4Yzw7OjRxOHxB8f3o9wO34V__IR5UkSf7LiOPhLSL-DR4MKlo5zwr8LFAf8h_oBtVTj8GIcAAYgB4YwSDACBiFBMPPGctY6a6pAAxighhEjKAAaBNsgIIAAQRgFFHCBGIACQIBJAoAAADCKiCDLSCCABQYQQwIwEigkArKGII0OUQEwAogBRoCCHCCKQAEcEkQYQYoQSigDjCBMCIUCJIUQJQQRRiDAAHSEKEOCCEAAgDRQBxDEgkBEGEAQQFkIIIAQhAgnBAFTAQIEAQYgxYwBClAkEACMEAEAAMQgISAxCgiiCACESIWQAUWYQBoBDBhBGgBBAMSMkYogAIwjwBCMkACLCCASEIMARg4QCBCAijCYAKweEAkAJYRgSAkDjjBCMQgioMIYBQIgDQhkBGiKEQAeBFAQAZoACBgFKFAEAOQMAEIQYgICShChGCCDKESSYoEIQAIRiFkAAgQJMCWMYRUAIgAQAigFEgFDEEAEwEAYQaQw0BgEHADDWGSCAWEgIBQQxBghmjBQCCEqMA0YpQIwAwgDjHFBECiWUEQYxohABRAhAjAUCESUARgRQYgAARggKMAVOAEIEc4gyJ4ABABCCjGMIKAIAEQIAIAwChAEgAGEAGAeIUMZY4QghSBhADSCCGiKNlAQoogAChjCDEAEEWEIRA0QohoQAQCkECEGQEQIEMUwYgIgBABgECECCKEQAAkIgYZARBgmADDNKIEAEoAgAAAQDBAgCHJCAEGG0QkQAaZgAAkpAkBAGImAgIYI5AoQAAiBBiCDMASGIYQAoB4QgCAlBIHFIICaAIM4aJawAxFIBDAFGGEA5AUQAgZhCTgJBgEKAACEMI4gwRRwQDAEEIQFEIaKIQYQBgYgBCjiGgAHEUQGYAIwwQASSylCjgJKMI8AIhIAAgAQwBBChhCIKAyOAVIIZAYBBihIIiBAACKMUUhI6JYAAigBADFAiAGBAhoZApRRQwABAiCCAGGcAQUIaBQBhgjBDACEEWSEsYAQYBIAVAACCmDAhEUAEEEQJhQA");
        }

        [Test]
        public void should_parse_fpcalc_text()
        {
            var text = @"FILE=Adele - 01 - 21 - Rolling in the Deep.flac
DURATION=229
[encoded data, 6984 characters]
";

            var result = Subject.ParseFpcalcTextOutput(text);
            result.Duration.Should().Be(229);
            result.Fingerprint.Should().Be("[encoded data, 6972 characters]");
        }

        [Test]
        public void should_parse_fpcalc_text_with_noninteger_duration()
        {
            var text = @"FILE=Adele - 01 - 21 - Rolling in the Deep.flac
DURATION=229.29
[encoded data, 6984 characters]
";

            var result = Subject.ParseFpcalcTextOutput(text);
            result.Duration.Should().Be(229.29);
            result.Fingerprint.Should().Be("[encoded data, 6972 characters]");
        }
        
        [TestCase("nin.mp3")]
        [TestCase("nin.flac")]
        public void should_fingerprint_file(string file)
        {
            var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", file);
            
            var fingerprint = Subject.GetFingerprint(path);
            fingerprint.Should().NotBeNull();
            fingerprint.Fingerprint.Should().Be("AQACmomSJEySRNISHCa6zDh6OO_hoUfr48cvHD83-JApYL6F8oCMHvlg46qOHYf740L6ascN_fj0wh90aD2OC41FC-Exf0IvPBKyH6qNOGLEgrBxXC3w4MiFB2J--Cce4cYXpLwGXER64RHxQxT142eJFMeL40g_HSbUh7h6xONhuDZ-5NpxFrpwfCrSo4pj_EJYHoehvzjeHcbnDGoOH30WPEYeEz3xI72P0sLRNRHx49IB_IXx4_iH5yF-HOdx2FoE8R5-HM2hJmOF6hFSXziPHdtxmLmQ5sKYHzouFjlMokfOBncsaE91mPoQ_MctTCqRX9CEnziO_zhcCPk_POmOoz8u1KOQ6-ihazgaHw9OaPlxAvmKfDhUpcWH_MNbBr-Do0eYH7p-5PqFPUbD5TK2o6p0_MeP8IcOw0c-H8eRZxCjRniE8HgPhlKKxqmk4jnai8JZBO9SPMauFEeOHxeOFj_-NsgFdaHxIzx8PMzQRsQfRL4GHvoiNLnwXD6uA-Jx_DiM4-Wh5nBUIXx8vEMtBt60wWwQ3mh7ovE1PCmaHMdx9AiOM8SFXMfVC_oToDl64sqSsfiNB-Wh5_iT4xf-D8dh6PjxAP6CP8fjQf9ghM069IYfwxf8C5cQdwcXC5-CPNiP48WBKh_i49DN4Dz6C82Rx8mQH7-wgzls5VDznPhz4PBx_AAr-PjxVBHUB-aHQld2oWfQODnOoKcLX7iW4fHBFcfxHPOgH_Mt_HjEJDoq9cKH44nyQyfCjBeeVBP4VEUfvIvwIIueUYWTJviFH_lx_EeOQ7wG1sibwNGL7oh_6GzQTGKIkFm64CE-1TiYH_6OWHXw_Dh-2Dp0_TgR43mOXjOOkOGhZdKHPHiIvgy2H_0xJlsQX9Cu48gN__iR5_jBHj7U6wiVtyj9oemOz8LR_Ba-IM8VXDPCJ1PBRdMRyhe8aYZ-HP3R48fBvdCeHM9R7Qve48htuMoS0eiR-_jxoDkYLjoeJ9DUU_iA4zr44zec4_EOPcdTeAib4URPPLCPnseniUL0D6HSHf9xoz3wByF73Ic-VA_-fYh_ePwQ_cGlQD-ap-jDHOEpXENWwrEyPMe1I8ePHz_yQz-8D_-NrIbzo7uF-IcuohkZXBpyH89jnAJFHSH5DP9R5fh0FDrB42mGazj-bbhz6DwahGSKq_jxGwx3-EIsbnh-wdYO4YSPHz8OQszxPMSPhsf3HDl6zTCRhwr6g1fxPAej44txfLhw6JiPisfb4LhzlDy0ZDhj5NqIo3-w_UA6Cn2GKk6hHtcAH7-JH4cDNSkeHS9yH9_x4cyQ6yIemM5xBefx9HCqGT-OHzxOaDwefLfwpBfyC-EP_9CZo88snEPOHl-EHn4QMSd-XAN2PAe8HdBlH9SLrzm6HH-hK0d5mCrOoj9-MMe3hrhycPERjw9-YciJHx-EP8cTsRvOw5OOHjpjY14yEj0ycbBxZUXEVHB25BrM4McOhCwwCCDgjAQAFIOoAIICIQSAQiBDFELAEaYUMMtAKgUSACBnRJEQEGCAeAoRRIQQliFAsVYGGOKIcEYAAIVRgjgAJDNGKYCUBgIIKLwxCBHjCVDGECYuAsJBDhUSBhGhCACGKKOEEUUI4AAxHAkFHQEAQWeQJAYIYGQUAgBBgNGAMAEQMABRJwQSD2gCGAIMAOUIYhQBKwBjBCKmlCIBAACUYmYJZA0gRDgBCDDwWQcRAAAARJxACoFuBABOAACIwlY5Q4BwQAEAJDDYKZGQwogIyQwSABFmFDHDCAKAUMwooYAQABEgACPEAEORcQQ4aAAgHBRBpFFMECUoUJQZs4ARSBEFgUHKOUGAAYQ5QxAQyAFADDlAKgKMUAIQBxpQjBDLIBNCAGKsIBQRRQSSwjkFkCPDEOEQIUwKJJiywADhtHGAEaKAUBASxRRBxBgCDFBAKYWAAkIAYQQQBAkLBFEAKEIexEYxQYhFBghiAEDECCABMQAACh1QiBAgCDBUIEUZQAAAwpxYADFzAIAEIQEwkAQIAJhwylElhINSOMEEAwwggJVSAjHjgBQIEcMQcUARBJRT8AKBgAMAGKMIABIxQYVwhACAFbKAAUEAccAR4wmRlAjCiEEGMGIcEAQYZCSCTCInBQ");
            fingerprint.Duration.Should().BeApproximately(85.11, 0.1);
        }

        [TestCase("nin.mp3")]
        [TestCase("nin.flac")]
        public void should_lookup_file(string file)
        {
            UseRealHttp();

            var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", file);
            var localTrack = new LocalTrack { Path = path };
            Subject.Lookup(new List<LocalTrack> { localTrack }, 0.5);
            localTrack.AcoustIdResults.Should().NotBeNull();
            localTrack.AcoustIdResults.Should().Contain("30f3f33e-8d0c-4e69-8539-cbd701d18f28");
        }

        [Test]
        public void should_lookup_list()
        {
            UseRealHttp();

            var files = new [] {
                "nin.mp3",
                "nin.flac"
            }.Select(x => new LocalTrack { Path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", x) }).ToList();
            Subject.Lookup(files, 0.5);

            files[0].AcoustIdResults.Should().Contain("30f3f33e-8d0c-4e69-8539-cbd701d18f28");
            files[1].AcoustIdResults.Should().Contain("30f3f33e-8d0c-4e69-8539-cbd701d18f28");
        }

        [Test]
        public void should_lookup_list_when_fpcalc_fails_for_some_files()
        {
            UseRealHttp();

            var files = new [] {
                "nin.mp3",
                "missing.mp3",
                "nin.flac"
            }.Select(x => new LocalTrack { Path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", x) }).ToList();

            var idpairs = files.Select(x => Tuple.Create(x, Subject.GetFingerprint(x.Path))).ToList();
            
            Subject.Lookup(idpairs, 0.5);

            files[0].AcoustIdResults.Should().Contain("30f3f33e-8d0c-4e69-8539-cbd701d18f28");
            files[1].AcoustIdResults.Should().BeNull();
            files[2].AcoustIdResults.Should().Contain("30f3f33e-8d0c-4e69-8539-cbd701d18f28");
        }

        [Test]
        public void should_lookup_list_when_fpcalc_fails_for_all_files()
        {
            UseRealHttp();

            var files = new [] {
                "missing1.mp3",
                "missing2.mp3"
            }.Select(x => new LocalTrack { Path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", x) }).ToList();

            var idpairs = files.Select(x => Tuple.Create<LocalTrack, AcoustId>(x, null)).ToList();
            
            Subject.Lookup(idpairs, 0.5);

            files[0].AcoustIdResults.Should().BeNull();
            files[1].AcoustIdResults.Should().BeNull();
        }

        [Test]
        public void should_not_fail_if_duration_reported_as_zero()
        {
            UseRealHttp();

            var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", "missing.mp3");
            var localTrack = new LocalTrack { Path = path };
            var acoustId = new AcoustId {
                Duration = 0,
                Fingerprint = "fingerprint"
            };

            Subject.Lookup(new List<Tuple<LocalTrack, AcoustId>> { Tuple.Create(localTrack, acoustId)}, 0.5);
        }

        [Test]
        public void should_not_throw_if_fingerprint_invalid()
        {
            UseRealHttp();

            var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", "missing.mp3");
            var localTrack = new LocalTrack { Path = path };
            var acoustId = new AcoustId {
                Duration = 1,
                Fingerprint = "fingerprint"
            };

            var files = new List<Tuple<LocalTrack, AcoustId>> { Tuple.Create(localTrack, acoustId)};
            Subject.Lookup(files, 0.5);
            files[0].Item1.AcoustIdResults.Should().BeNull();
        }

        [Test]
        public void should_not_fail_for_some_invalid_fingerprints()
        {
            UseRealHttp();

            var files = new [] {
                "nin.mp3",
                "nin.flac"
            }.Select(x => new LocalTrack { Path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", x) }).ToList();

            var idpairs = files.Select(x => Tuple.Create(x, Subject.GetFingerprint(x.Path))).ToList();

            idpairs.Add(Tuple.Create(new LocalTrack(), new AcoustId { Duration = 1, Fingerprint = "fingerprint" }));
            
            Subject.Lookup(idpairs, 0.5);

            idpairs[0].Item1.AcoustIdResults.Should().Contain("30f3f33e-8d0c-4e69-8539-cbd701d18f28");
            idpairs[1].Item1.AcoustIdResults.Should().Contain("30f3f33e-8d0c-4e69-8539-cbd701d18f28");
            idpairs[2].Item1.AcoustIdResults.Should().BeNull();
        }

        [Test]
        public void should_not_throw_if_api_returns_html()
        {
            Mocker.GetMock<IHttpClient>().Setup(x => x.Post<LookupResponse>(It.IsAny<HttpRequest>()))
                                         .Callback<HttpRequest>(req => throw new UnexpectedHtmlContentException(new HttpResponse(req, req.Headers, "html content", HttpStatusCode.Accepted)));

            var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", "nin.mp3");
            var localTrack = new LocalTrack { Path = path };
            Subject.Lookup(new List<LocalTrack> { localTrack }, 0.5);
            localTrack.AcoustIdResults.Should().BeNull();

            ExceptionVerification.ExpectedWarns(1);
        }

        [Test]
        public void should_not_throw_if_api_times_out()
        {
            Mocker.GetMock<IHttpClient>().Setup(x => x.Post<LookupResponse>(It.IsAny<HttpRequest>()))
                .Throws(new System.Net.WebException("The operation has timed out."));

            var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", "nin.mp3");
            var localTrack = new LocalTrack { Path = path };
            Subject.Lookup(new List<LocalTrack> { localTrack }, 0.5);
            localTrack.AcoustIdResults.Should().BeNull();

            ExceptionVerification.ExpectedWarns(1);
        }
    }
}
