"""Tests for CSV exercises"""
import os
from textwrap import dedent

from helpers import make_file, run_program, ModuleTestCase


class PipeToCommaTests(ModuleTestCase):

    """
    Tests for pipe_to_comma.py

    Convert pipe-separated file to a comma-separated file.
    """

    module_path = "pipe_to_comma.py"

    def test_single_column(self):
        inputs = [
            "line1",
            "line2",
            "line3",
        ]
        with make_file("\n".join(inputs)) as file1, make_file("") as file2:
            run_program("pipe_to_comma.py", [file1, file2])
            with open(file2) as csv_file:
                outputs = csv_file.read().splitlines()
        self.assertEqual(inputs, outputs)

    def test_two_columns(self):
        inputs = [
            "a|b",
            "c|d",
            "e|f",
        ]
        expected = [
            "a,b",
            "c,d",
            "e,f",
        ]
        with make_file("\n".join(inputs)) as file1, make_file("") as file2:
            run_program("pipe_to_comma.py", [file1, file2])
            with open(file2) as csv_file:
                outputs = csv_file.read().splitlines()
        self.assertEqual(outputs, expected)

    def test_quotes_and_delimeter_usage(self):
        inputs = [
            "oh what a day, what a lovely day",
            "this line has two columns|yes 2",
            '"this line has | in quotes"',
        ]
        expected = [
            '"oh what a day, what a lovely day"',
            "this line has two columns,yes 2",
            "this line has | in quotes",
        ]
        with make_file("\n".join(inputs)) as file1, make_file("") as file2:
            run_program("pipe_to_comma.py", [file1, file2])
            with open(file2) as csv_file:
                outputs = csv_file.read().splitlines()
        self.assertEqual(outputs, expected)


class TotalAirTravelTests(ModuleTestCase):

    """
    Tests for total_air_travel.py

    Print out sum of all Air Travel expenses.
    """

    module_path = "total_air_travel.py"

    def test_no_air_travel_expenses(self):
        contents = dedent(
            """
            Date,Merchant,Cost,Category
            2/01/2017,Zapier,15.00,Software
            2/05/2017,Lyft,24.24,Ground Transport
            2/06/2017,Lyft,15.65,Ground Transport
            2/17/2017,Mailchimp,19.80,Software
            2/17/2017,Lyft,12.06,Ground Transport
            2/21/2017,Uber.com,11.02,Ground Transport
            2/21/2017,Hyatt,196.24,Hotel
            2/22/2017,Uber.com,4.85,Ground Transport
            2/24/2017,Hyatt,496.05,Hotel
            2/24/2017,Lyft,12.09,Ground Transport
            3/02/2017,Zapier,15.00,Software
            3/08/2017,Lyft,11.50,Ground Transport
            3/12/2017,Hyatt,1070.90,Hotel
            3/14/2017,Lyft,20.10,Ground Transport
            3/17/2017,Mailchimp,24.75,Software
            3/27/2017,Amtrak,112.70,Ground Transport
        """).lstrip()
        with make_file(contents) as expense_file:
            output = run_program("total_air_travel.py", [expense_file])
        self.assertEqual(output, "0\n")

    def test_some_air_travel(self):
        contents = dedent("""
            Date,Merchant,Cost,Category
            9/03/2017,Southwest Airlines,133.90,Air Travel
            9/01/2017,Zapier,49.00,Software
            9/10/2017,Delta,145.20,Air Travel
            9/12/2017,Alaska Air,118.20,Air Travel
            9/17/2017,Mailchimp,29.70,Software
            9/18/2017,Lyft,27.23,Ground Transport
            9/20/2017,Lyft,13.00,Ground Transport
            9/20/2017,Atherton Park Inn,1270.53,Hotel
            9/21/2017,Lyft,43.05,Ground Transport
            9/21/2017,Lyft,11.55,Ground Transport
            9/22/2017,Lyft,24.94,Ground Transport
            9/24/2017,Lyft,12.86,Ground Transport
            9/24/2017,Lyft,28.50,Ground Transport
            9/25/2017,Lyft,9.50,Ground Transport
        """).lstrip()
        with make_file(contents) as expense_file:
            output = run_program("total_air_travel.py", [expense_file])
        self.assertEqual(output, "397.3\n")


class ReorderTests(ModuleTestCase):

    """
    Tests for reorder.py

    Read CSV file, swap first two columns, and write the CSV to a new file.
    """

    module_path = "reorder.py"

    def test_swap_columns(self):
        filename = "us-state-capitals.csv"
        new_filename = "new-file.csv"
        run_program("reorder.py", [filename, new_filename])
        with open(new_filename) as new_file:
            lines = new_file.read().splitlines()
        os.remove(new_filename)
        self.assertEqual(lines[0], "capital,state")
        self.assertEqual(lines[-1], "Cheyenne,Wyoming")
        self.assertEqual(len(lines), 51)

    def test_swap_columns_twice(self):
        filename1 = "us-state-capitals.csv"
        filename2 = "reordered.csv"
        filename3 = "original.csv"
        run_program("reorder.py", [filename1, filename2])
        run_program("reorder.py", [filename2, filename3])
        with open(filename1) as file1:
            contents1 = file1.read().splitlines()
        with open(filename3) as file3:
            contents3 = file3.read().splitlines()
        os.remove(filename2)
        os.remove(filename3)
        self.assertEqual(contents1, contents3)


class SortByColumnTests(ModuleTestCase):

    """Tests for sort_by_column.py"""

    module_path = "sort_by_column.py"
    maxDiff = None

    def test_sort_by_first_column(self):
        contents = dedent("""
            Year,Make,Model
            2012,Lexus,LFA
            2009,GMC,Yukon XL 1500
            1965,Ford,Mustang
            2005,Hyundai,Sonata
            1995,Mercedes-Benz,C-Class
        """).lstrip()
        expected = dedent("""
            Year,Make,Model
            1965,Ford,Mustang
            1995,Mercedes-Benz,C-Class
            2005,Hyundai,Sonata
            2009,GMC,Yukon XL 1500
            2012,Lexus,LFA
        """).lstrip()
        with make_file(contents) as in_filename, make_file('') as out_filename:
            run_program('sort_by_column.py', [in_filename, out_filename, '0'])
            with open(out_filename) as out_file:
                output = out_file.read()
        self.assertEqual(expected, output)

    def test_sort_by_second_column(self):
        contents = dedent("""
            Year,Make,Model
            2012,Lexus,LFA
            2009,GMC,Yukon XL 1500
            1965,Ford,Mustang
            2005,Hyundai,Sonata
            1995,Mercedes-Benz,C-Class
        """).lstrip()
        expected = dedent("""
            Year,Make,Model
            1965,Ford,Mustang
            2009,GMC,Yukon XL 1500
            2005,Hyundai,Sonata
            2012,Lexus,LFA
            1995,Mercedes-Benz,C-Class
        """).lstrip()
        with make_file(contents) as in_filename, make_file('') as out_filename:
            run_program('sort_by_column.py', [in_filename, out_filename, '1'])
            with open(out_filename) as out_file:
                output = out_file.read()
        self.assertEqual(expected, output)

    def test_sorts_by_specified_column_only(self):
        contents = dedent("""
            N,Artist,Title
            11,Johnny Cash,Folsom Prison Blues
            13,Billy Joe Shaver,Low Down Freedom
            2,Waylon Jennings,Honky Tonk Heroes (Like Me)
            2,Hank Williams III,Mississippi Mud
            4,Kris Kristofferson,To Beat The Devil
            22,David Allan Coe,"Willie, Waylon, And Me"
            4,Bob Dylan,House Of The Risin' Sun
        """).lstrip()
        expected = dedent("""
            N,Artist,Title
            11,Johnny Cash,Folsom Prison Blues
            13,Billy Joe Shaver,Low Down Freedom
            2,Waylon Jennings,Honky Tonk Heroes (Like Me)
            2,Hank Williams III,Mississippi Mud
            22,David Allan Coe,"Willie, Waylon, And Me"
            4,Kris Kristofferson,To Beat The Devil
            4,Bob Dylan,House Of The Risin' Sun
        """).lstrip()
        with make_file(contents) as in_filename, make_file('') as out_filename:
            run_program('sort_by_column.py', [in_filename, out_filename, '0'])
            with open(out_filename) as out_file:
                output = out_file.read()
        self.assertEqual(expected, output)


class UnGroupTests(ModuleTestCase):

    """
    Tests for ungroup.py

    Un-group first column of CSV file.
    """

    module_path = "ungroup.py"

    def test_single_row(self):
        inputs = [
            "Category,Item,Expense",
        ]
        with make_file("\n".join(inputs)) as file1, make_file("") as file2:
            run_program("ungroup.py", [file1, file2])
            with open(file2) as csv_file:
                outputs = csv_file.read().splitlines()
        self.assertEqual(inputs, outputs)

    def test_no_need_to_ungroup(self):
        inputs = [
            "Category,Item,Expense",
            "Swag,rubber ducks,$50",
            "Food,breakfast,$300",
        ]
        with make_file("\n".join(inputs)) as file1, make_file("") as file2:
            run_program("ungroup.py", [file1, file2])
            with open(file2) as csv_file:
                outputs = csv_file.read().splitlines()
        self.assertEqual(inputs, outputs)

    def test_one_group(self):
        inputs = [
            "Category,Item",
            "Swag,rubber ducks",
            ",stickers",
            ",balloons",
        ]
        expected = [
            "Category,Item",
            "Swag,rubber ducks",
            "Swag,stickers",
            "Swag,balloons",
        ]
        with make_file("\n".join(inputs)) as file1, make_file("") as file2:
            run_program("ungroup.py", [file1, file2])
            with open(file2) as csv_file:
                outputs = csv_file.read().splitlines()
        self.assertEqual(expected, outputs)

    def test_multiple_groups(self):
        inputs = [
            "Category,Item,Expense",
            "Swag,rubber ducks,$50",
            ",stickers,$150",
            ",ducks,$40",
            ",mugs,$120",
            ",shirts,$80",
            "Food,breakfast,$300",
            ",lunch,$600",
            ",coffee,$130",
            ",snacks,$25",
            "Venue,parking,$200",
            ",room rental,$300",
            ",extra tables,$50",
            "Decoration,balloons,$20",
            ",streamers,$10",
            ",signs,$20",
        ]
        expected = [
            "Category,Item,Expense",
            "Swag,rubber ducks,$50",
            "Swag,stickers,$150",
            "Swag,ducks,$40",
            "Swag,mugs,$120",
            "Swag,shirts,$80",
            "Food,breakfast,$300",
            "Food,lunch,$600",
            "Food,coffee,$130",
            "Food,snacks,$25",
            "Venue,parking,$200",
            "Venue,room rental,$300",
            "Venue,extra tables,$50",
            "Decoration,balloons,$20",
            "Decoration,streamers,$10",
            "Decoration,signs,$20",
        ]
        with make_file("\n".join(inputs)) as file1, make_file("") as file2:
            run_program("ungroup.py", [file1, file2])
            with open(file2) as csv_file:
                outputs = csv_file.read().splitlines()
        self.assertEqual(expected, outputs)


if __name__ == "__main__":
    from helpers import error_message

    error_message()
