#! /usr/bin/env python
# -*- coding: utf-8 -*-
from selenium import webdriver
import time
import logging
import random
import re
import collections

logging.basicConfig(level=logging.INFO)

_TIME_WAIT_TO_LOAD = 5
_TIME_WAIT_TO_REPLY = 15
_TIME_INTERVAL = 5
_COLLECT_COUNT = 100
_REPLY_POST_COUNT = random.randint(35, 40)
_MOST_TEN = 10
_NUMBER_RE = re.compile('\.*\s*(\d+)')
_MESSAGE_MAX_LENGTH = 10
_REPLY_MIN_COUNT = 10


class AutoMeizuCommunity(object):

    def __init__(self):
        url = "http://bbs.meizu.cn/forum-22-1.html"
        self.browser = webdriver.Chrome()
        self.browser.maximize_window()
        # self.browser.set_window_size(300, 300)
        self.browser.get(url)

    def execute(self):
        # time to login manually, 60s
        time.sleep(60)
        window_size = self.browser.get_window_size(self.browser.current_window_handle)
        self.browser.set_window_size(100, 100)
        self.browser.set_window_position(window_size['width'], window_size['height'], self.browser.current_window_handle)

        zong_he_tao_lun_window_handle = self.browser.current_window_handle

        reply_post_count = 0
        page_count = 1
        try:
            page_bottom_span = self.browser.find_element_by_id("fd_page_bottom")
            last_button = page_bottom_span.find_element_by_css_selector("a.last")
            next_button = page_bottom_span.find_element_by_css_selector("a.nxt")
            page_count = int(_NUMBER_RE.match(last_button.text).groups()[0])
        except Exception as e:
            logging.error("Get ZongHeTaoLun page count error:")
            logging.error(e)
        logging.info("ZongHeTaoLun page count: %d" % page_count)

        for page_num in range(1, page_count + 1):
            if reply_post_count > _REPLY_POST_COUNT:
                break

            table_ele = self.browser.find_element_by_css_selector("form[id='moderate']>table")
            tbody_eles = table_ele.find_elements_by_css_selector("tbody[id^='normalthread_']")
            for tbody_ele in tbody_eles:
                new_window_opened = False
                try:
                    post_title_ele = tbody_ele.find_element_by_css_selector("div[id^='maincont_list_']>a")
                    post_title_ele.click()
                    self._wait_to_load()

                    self._switch_to_new_window()
                    new_window_opened = True

                    if self._has_reply_button():
                        reply_message = self._get_message_to_reply()
                        if reply_message:
                            self._reply_message(reply_message)
                            self._wait_to_reply()
                            reply_post_count += 1
                            if reply_post_count > _REPLY_POST_COUNT:
                                break

                except Exception as e:
                    current_title = ''
                    current_url = ''

                    # sometimes self.browser.title also gets exception, e.g. when timeout exception.
                    try:
                        current_url = self.browser.current_url
                        current_title = self.browser.title
                    except Exception:
                        pass

                    logging.error("Exception in main: %s(%s)" % (current_title, current_url))
                    logging.error(e)

                    # TODO: when net is broken, wait util net is recovered.
                    
                finally:
                    if new_window_opened:
                        self.browser.close()
                    self.browser.switch_to.window(zong_he_tao_lun_window_handle)
                    self._wait_to_load()

            if page_num < page_count:
                next_button.click()
                self._wait_to_load()

                # renew next button
                page_bottom_span = self.browser.find_element_by_id("fd_page_bottom")
                next_button = page_bottom_span.find_element_by_css_selector("a.nxt")

        self.browser.quit()

    def _switch_to_new_window(self):
        self.browser.switch_to.window(self.browser.window_handles[-1])

    def _get_message_to_reply(self):
        result_message = None

        page_count = 1
        try:
            foot_post_div = self.browser.find_element_by_css_selector("div.footdiv_post")
            last_button = foot_post_div.find_element_by_css_selector("a.last")
            # next_button = foot_post_div.find_element_by_css_selector("a.nxt")
            page_count = int(_NUMBER_RE.match(last_button.text).groups()[0])
        except Exception:
            pass

        # move to last page
        if page_count > 1:
            last_button.click()
            self._wait_to_load()
            foot_post_div = self.browser.find_element_by_css_selector("div.footdiv_post")
            prev_button = foot_post_div.find_element_by_css_selector("a.prev")

        reply_messages = []

        for page_num in range(page_count, 0, -1):
            if len(reply_messages) >= _COLLECT_COUNT:
                break

            reply_post_list_div = self.browser.find_element_by_css_selector("div[id='ct']")
            reply_posts = reply_post_list_div.find_elements_by_css_selector("div[id^='post_']")

            # TODO: temp solution
            if len(reply_posts) > 1:
                if page_num == 1:
                    reply_posts = reply_posts[1:]
                if len(reply_posts) > 1:
                    reply_posts = reply_posts[:-1]

            for reply_post in reply_posts:
                try:
                    post_message_ele = reply_post.find_element_by_css_selector("td[id^='postmessage_']>div")
                    message_text = post_message_ele.text
                    message_text = message_text.strip()
                    if 0 < len(message_text) <= _MESSAGE_MAX_LENGTH:
                        reply_messages.append(message_text)
                        if len(reply_messages) >= _COLLECT_COUNT:
                            break
                except Exception as e:
                    logging.error('Exception in get message: %s(%s)' % (self.browser.title, self.browser.current_url))
                    logging.error(e)

            if page_num > 1:
                prev_button.click()
                self._wait_to_load()

                # renew prev button
                foot_post_div = self.browser.find_element_by_css_selector("div.footdiv_post")
                prev_button = foot_post_div.find_element_by_css_selector("a.prev")

        if len(reply_messages) < _REPLY_MIN_COUNT:
            logging.warning('Too little replies(%d) in the post: %s(%s)' % (len(reply_messages), self.browser.title, self.browser.current_url))
            return result_message

        messages_counter = collections.Counter(reply_messages)
        most_ten = _MOST_TEN
        if len(reply_messages) < most_ten:
            most_ten = len(reply_messages)
        most_common = messages_counter.most_common(most_ten)