# -*- encoding: UTF8 -*-
# Test harness for swarm_reviews.py

from __future__ import print_function

import sys
import unittest
import os

sys.path.append(os.path.join('..', '..', 'bin', 'triggers', 'tests'))
sys.path.append('.')
from p4testutils import TestCase, P4Server, localDirectory, create_file, append_to_file

# parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# sys.path.insert(0, parent_dir)
from swarm_reviews import Review, SwarmReviews

os.environ["LOGS"] = "."
LOGGER_NAME = "TestSwarmReviews"
LOG_FILE = "log-SwarmReviews.log"

python3 = sys.version_info[0] >= 3

if python3:
    from unittest.mock import patch, Mock
else:
    from mock import patch, Mock

"""
100   681  100   681    0     0    724      0 --:--:-- --:--:-- --:--:--   724
{
    "review": {
        "approvals": None,
        "author": "Joe_Coder",
        "changes": [
            790
        ],
        "commitStatus": [],
        "commits": [
            790
        ],
        "created": 1532514869,
        "deployDetails": [],
        "deployStatus": None,
        "description": "corrected new method cState\n",
        "groups": [],
        "id": 851,
        "participants": {
            "Joe_Coder": [],
            "bruno": {
                "vote": {
                    "isStale": false,
                    "value": -1,
                    "version": 1
                }
            },
            "super": {
                "vote": {
                    "isStale": false,
                    "value": 1,
                    "version": 1
                }
            }
        },
        "pending": false,
        "projects": {
            "default": [
                "main"
            ]
        },
        "state": "needsReview",
        "stateLabel": "Needs Review",
        "testDetails": [],
        "testStatus": None,
        "type": "default",
        "updated": 1532515053,
        "versions": [
            {
                "addChangeMode": "replace",
                "change": 790,
                "difference": 1,
                "pending": false,
                "stream": None,
                "time": 1108972972,
                "user": "Joe_Coder"
            }
        ]
    }
}
"""

class TestSwarmReviews(TestCase):
    def __init__(self, methodName='runTest'):
        super(TestSwarmReviews, self).__init__(LOGGER_NAME, LOG_FILE, methodName=methodName)

    def setUp(self):
        pass

    def tearDown(self):
        pass

    def testReviews(self):
        json = {
            "review": {
                "author": "fbloggs",
                "changes": [
                    1683251,
                    1683261
                ],
                "commitStatus": [],
                "commits": [],
                "created": 1532407788,
                "deployDetails": [],
                "deployStatus": None,
                "description": "Follow-on to change 123423.\n\nInfrastructure-only change.\n",
                "groups": [
                    "perforce",
                    "swarm",
                    "swarm-project-p4d",
                ],
                "id": 1683260,
                "participants": {
                    "Joe_Coder": [],
                    "bruno": {
                        "vote": {
                            "isStale": False,
                            "value": -1,
                            "version": 1
                        }
                    },
                    "super": {
                        "vote": {
                            "isStale": False,
                            "value": 1,
                            "version": 1
                        }
                    },
                    "fred": {
                        "vote": {
                            "isStale": False,
                            "value": 1,
                            "version": 1
                        }
                    }
                },
                "pending": True,
                "projects": {
                    "p4d": [
                        "main"
                    ]
                },
                "reviewerGroups": {
                    "server-approvers": {
                        "quorum": "1",
                        "required": True
                    }
                },
                "state": "approved",
                "stateLabel": "Approved",
                "testDetails": [],
                "testStatus": None,
                "type": "default",
                "updated": 1532410662,
                "versions": [
                    {
                        "addChangeMode": "replace",
                        "archiveChange": 1683261,
                        "change": 1683260,
                        "difference": 1,
                        "pending": True,
                        "stream": None,
                        "time": 1532407788,
                        "user": "fbloggs"
                    }
                ]
            }
        }
        r = Review(json)
        self.assertEqual('fbloggs', r.author())
        self.assertEqual(2, r.numUpVotes())
        self.assertEqual(1, r.numDownVotes())
        r.addComments(
            [
                {"attachments": [], "batched": False, "body": "Are you sure - cmt-8",
                "context": {"review": 848, "version": 1},
                "edited": None,
                    "flags": [],
                    "likes": None,
                    "readBy": [
                        "super"
                    ],
                    "taskState": "comment",
                    "time": 1510350663,
                    "topic": "reviews/848",
                    "updated": 1524211211,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": False,
                    "body": "My comment in reply",
                    "context": {
                        "change": None,
                        "comment": 6,
                        "content": None,
                        "file": None,
                        "leftLine": None,
                        "line": None,
                        "md5": None,
                        "name": "",
                        "review": 848,
                        "rightLine": None,
                        "version": 1
                    },
                    "edited": None,
                    "flags": [],
                    "likes": [],
                    "readBy": [
                        "super"
                    ],
                    "taskState": "comment",
                    "time": 1511521507,
                    "topic": "reviews/848",
                    "updated": 1524211211,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": False,
                    "body": "Step 3",
                    "context": {
                        "change": None,
                        "comment": 13,
                        "content": None,
                        "file": None,
                        "leftLine": None,
                        "line": None,
                        "md5": None,
                        "name": "",
                        "review": 848,
                        "rightLine": None,
                        "version": 1
                    },
                    "edited": None,
                    "flags": [],
                    "likes": None,
                    "readBy": [
                        "super"
                    ],
                    "taskState": "comment",
                    "time": 1511521516,
                    "topic": "reviews/848",
                    "updated": 1524211211,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": False,
                    "body": "Step 4",
                    "context": {
                        "change": None,
                        "comment": 14,
                        "content": None,
                        "file": None,
                        "leftLine": None,
                        "line": None,
                        "md5": None,
                        "name": "",
                        "review": 848,
                        "rightLine": None,
                        "version": 1
                    },
                    "edited": None,
                    "flags": [],
                    "likes": None,
                    "readBy": [
                        "super"
                    ],
                    "taskState": "comment",
                    "time": 1511521524,
                    "topic": "reviews/848",
                    "updated": 1524211211,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": False,
                    "body": "Step 5 asdfasdffasd",
                    "context": {
                        "change": None,
                        "comment": 15,
                        "content": None,
                        "file": None,
                        "leftLine": None,
                        "line": None,
                        "md5": None,
                        "name": "",
                        "review": 848,
                        "rightLine": None,
                        "version": 1
                    },
                    "edited": 1511523837,
                    "flags": [],
                    "likes": [],
                    "readBy": [
                        "super"
                    ],
                    "taskState": "open",
                    "time": 1511521531,
                    "topic": "reviews/848",
                    "updated": 1524211211,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": False,
                    "body": "Another one",
                    "context": {
                        "change": None,
                        "comment": 14,
                        "content": None,
                        "file": None,
                        "leftLine": None,
                        "line": None,
                        "md5": None,
                        "name": "",
                        "review": 848,
                        "rightLine": None,
                        "version": 1
                    },
                    "edited": None,
                    "flags": [],
                    "likes": None,
                    "readBy": [
                        "super"
                    ],
                    "taskState": "comment",
                    "time": 1511521654,
                    "topic": "reviews/848",
                    "updated": 1524211211,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": True,
                    "body": "My first comment",
                    "context": {
                        "review": 851,
                        "version": 1
                    },
                    "edited": None,
                    "flags": [],
                    "likes": [],
                    "readBy": [],
                    "taskState": "addressed",
                    "time": 1532514892,
                    "topic": "reviews/851",
                    "updated": 1532515053,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": True,
                    "body": "Second comment (not a task)",
                    "context": {
                        "review": 851,
                        "version": 1
                    },
                    "edited": None,
                    "flags": [],
                    "likes": [],
                    "readBy": [],
                    "taskState": "comment",
                    "time": 1532514903,
                    "topic": "reviews/851",
                    "updated": 1532514903,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": False,
                    "body": "Third comment - also a task",
                    "context": {
                        "review": 851,
                        "version": 1
                    },
                    "edited": None,
                    "flags": [],
                    "likes": [],
                    "readBy": [],
                    "taskState": "open",
                    "time": 1532514931,
                    "topic": "reviews/851",
                    "updated": 1532516731,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": False,
                    "body": "Fix - so task addressed",
                    "context": {
                        "change": None,
                        "comment": 18,
                        "content": None,
                        "file": None,
                        "leftLine": None,
                        "line": None,
                        "md5": None,
                        "name": "",
                        "review": 851,
                        "rightLine": None,
                        "version": 1
                    },
                    "edited": None,
                    "flags": [],
                    "likes": [],
                    "readBy": [],
                    "taskState": "comment",
                    "time": 1532515049,
                    "topic": "reviews/851",
                    "updated": 1532516849,
                    "user": "bruno"
                }
            ])
        self.assertEqual(7, r.numComments())
        self.assertEqual(2, r.numOpenTasks())
        self.assertEqual(1, r.numClosedTasks())


    # @patch('SwarmReviews.requests')
    # def testSwarmReviews(self, requests_mock):
    #     """trigger fires and sends expected info to Swarm"""
#         self.server = P4Server()
#         config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "~test_config.yaml")
#         p4 = self.server.p4
#         p4.logger = self.logger
#
#         inside = localDirectory(self.server.client_root, "inside")
#         inside_file1 = os.path.join(inside, "inside_file1")
#         create_file(inside_file1, 'Test content')
#
#         p4.run('add', inside_file1)
#         result = p4.run('submit', '-d', 'inside_file1 added')
#         self.assertEqual("1", result[-1]['submittedChange'])
#
#         outside = localDirectory(self.server.client_root, "outside")
#         outside_file1 = os.path.join(outside, "outside_file1")
#         create_file(outside_file1, 'Test content')
#
#         p4.run('add', outside_file1)
#         result = p4.run('submit', '-d', 'outside_file1 added')
#         self.assertEqual("2", result[-1]['submittedChange'])
#
#         p4.run('edit', inside_file1)
#         append_to_file(inside_file1, "New line")
#         result = p4.run('submit', '-d', 'inside_file1 edited')
#         self.assertEqual("3", result[-1]['submittedChange'])
#
#         p4.run('edit', inside_file1)
#         append_to_file(inside_file1, "New line")
#         result = p4.run('submit', '-d', 'inside_file1 edited again')
#         self.assertEqual("4", result[-1]['submittedChange'])
#
#         trig_args = ["-p", p4.port, "-u", p4.user, "-c", config_path, "--test-mode", "1"]
#         get_call_count = 0
#         post_call_count = 0
#         patch_call_count = 0
#
#         # Test exclusionary mapping
#         with open(config_path, "w") as f:
#             f.write("""
# api: "api/v6"
# user: swarmtest
# ticket: A123453
# review_description:
#   - "Please review me!"
#   - "Don't forget to check YYYY"
# projects:
#   - name:           ProjectA
#     post_submit_create_review:  y
#     require_job:    y
#     update_review:  n
#     depot_paths:
#     - //depot/inside/...
#     - "-//depot/inside/*_file1"
#     default_reviewers:
#     - user1
#     - user2
# """)
#
#         trig = SwarmReviews(*trig_args)
#         result = trig.run()
#         self.assertEqual(0, result)
#         # Hasn't been called
#         self.assertEqual(get_call_count, requests_mock.get.call_count)
#         self.assertEqual(post_call_count, requests_mock.post.call_count)
#         self.assertEqual(patch_call_count, requests_mock.patch.call_count)
#
#         with open(config_path, "w") as f:
#             f.write("""
# api: "api/v6"
# user: swarmtest
# ticket: A123453
# review_description:
#   - "Please review me!"
#   - "Don't forget to check YYYY"
# projects:
#   - name:           ProjectA
#     post_submit_create_review:  y
#     require_job:    y
#     update_review:  y
#     depot_paths:
#     - //depot/inside/...
#     default_reviewers:
#     - user1
#     - user2
# """)
#
#         #----------------------------------------
#         # For a path config file defines as inside we should call.
#
#         mock_post_response = Mock()
#         mock_post_response.json.return_value = {"review": {
#                         "id":123, "author": "swarmtest", "commits": [817],
#                         "commitStatus":[],"created":1509095267,"deployDetails":[],"deployStatus":None,
#                         "description":"asdfasdf","groups":["longlived"],
#                         "participants": {"swarmtest":[], "user1":[], "user2":[]},
#                         "state": "needsReview"}}
#
#         # Assign our mock response as the result of our patched function
#         requests_mock.post.return_value = mock_post_response
#
#         trig = SwarmReviews(*trig_args)
#         result = trig.run()
#         self.assertEqual(0, result)
#         post_call_count += 1    # Expect an update
#         patch_call_count += 1
#         self.assertEqual(get_call_count, requests_mock.get.call_count)
#         self.assertEqual(post_call_count, requests_mock.post.call_count)
#         self.assertEqual(patch_call_count, requests_mock.patch.call_count)
#         args, kwargs = requests_mock.post.call_args_list[post_call_count - 1]
#         self.assertEqual(('http://swarm.dev/api/v6/reviews',), args)
#         self.assertDictEqual({'auth': ('swarmtest', 'A123453'),
#                               'data': [('change', '1'),
#                                         ('description', "Please review me!\nDon't forget to check YYYY"),
#                                         ('reviewers[]', 'user1'),
#                                         ('reviewers[]', 'user2')]}, kwargs)
#         args, kwargs = requests_mock.patch.call_args_list[patch_call_count - 1]
#         self.assertEqual(('http://swarm.dev/api/v6/reviews/123',), args)
#         self.assertDictEqual({'auth': ('swarmtest', 'A123453'),
#                               'data': [('author', p4.user)]}, kwargs)


if __name__ == '__main__':
    unittest.main()
