from __future__ import absolute_import
import re
try:
    import urlparse
except:
    import urllib.parse as urlparse
from bs4 import BeautifulSoup
from amazon_scraper import (
    get,
    review_url,
    extract_review_id,
    extract_reviewer_id,
    process_rating,
    strip_html_tags,
    dict_acceptable,
    retry,
    get_review_date,
    html_parser,
    amazon_base,
)

if 'unicode' not in dir(globals()['__builtins__']):
    unicode = str


class Review(object):
    def __init__(self, api, Id=None, URL=None, parserinfo=None):
        if Id and not URL:
            if 'amazon' in Id:
                raise ValueError('URL passed as ID')

            URL = review_url(Id)

        if not URL:
            raise ValueError('Invalid review page parameters')

        self.api = api
        self._URL = URL
        self._id = extract_review_id(URL)
        self._soup = None
        self.parserinfo = parserinfo

    @property
    @retry()
    def soup(self):
        if not self._soup:
            r = get(self.url, self.api)
            self._soup = BeautifulSoup(r.text, html_parser)
        return self._soup

    @property
    def id(self):
        #anchor = self.soup.find('a', attrs={'name': True}, text=False)
        #id_ = unicode(anchor['name'])
        #return id_
        return self._id

    @property
    def asin(self):
        tag = self.soup.find('abbr', class_='asin')
        asin = unicode(tag.string)
        return asin

    @property
    def url(self):
        return review_url(self.id)

    @property
    def title(self):
        tag = self.soup.find('span', class_='summary')
        title = unicode(tag.string)
        return title.strip()

    @property
    def rating(self):
        """The rating of the product normalised to 1.0
        """
        for li in self.soup.find_all('li', class_='rating'):
            # get the second string
            string = next(li.stripped_strings).lower()
            if 'overall:' not in string:
                continue

            img = li.find('img')
            rating = unicode(img['title'])
            return process_rating(rating)

    @property
    def date(self):
        abbr = self.soup.find('abbr', class_='dtreviewed')
        return get_review_date(abbr["title"], self.parserinfo)

    @property
    def user(self):
        vcard = self.soup.find('span', class_='reviewer vcard')
        if vcard:
            tag = vcard.find(class_='fn')
            if tag:
                user = unicode(tag.string)
                return user
        return None

    @property
    def user_id(self):
        url = self.user_reviews_url
        if url:
            return extract_reviewer_id(url)

    def user_reviews(self):
        url = self.user_reviews_url
        if url:
            return self.api.user_reviews(URL=url)

    @property
    def user_reviews_url(self):
        vcard = self.soup.find('span', class_='reviewer vcard')
        if vcard:
            anchor = vcard.find('a', href=re.compile(r'/pdp/'))
            if anchor:
                path = anchor.attrs['href']
                path = path.replace('/pdp/', '/cdp/')
                path = path.replace('/profile/', '/member-reviews/')
                return urlparse.urljoin(amazon_base, path)

    @property
    def text(self):
        tag = self.soup.find('span', class_='description')
        return strip_html_tags(unicode(tag))

    def product(self):
        return self.api.product(ItemId=self.asin)

    def to_dict(self):
        d = {
            k: getattr(self, k)
            for k in dir(self)
            if dict_acceptable(self, k, blacklist=['soup', '_URL', '_soup'])
        }
        return d
