"""Implementation of a search source based on our internal data."""

from ichnaea.api.locate.cell import (
    CellPositionMixin,
    CellRegionMixin,
)
from ichnaea.api.locate.constants import DataSource
from ichnaea.api.locate.source import (
    PositionSource,
    RegionSource,
)
from ichnaea.api.locate.wifi import (
    WifiPositionMixin,
    WifiRegionMixin,
)


class InternalRegionSource(CellRegionMixin,
                           WifiRegionMixin, RegionSource):
    """A region source based on our own crowd-sourced internal data."""

    fallback_field = None  #:
    source = DataSource.internal  #:

    def should_search(self, query, results):
        if not super(InternalRegionSource, self).should_search(
                query, results):  # pragma: no cover
            return False
        if not (self.should_search_cell(query, results) or
                self.should_search_wifi(query, results)):
            return False
        return True

    def search(self, query):
        results = self.result_type().new_list()

        for should, search in (
                (self.should_search_wifi, self.search_wifi),
                (self.should_search_cell, self.search_cell)):

            if should(query, results):
                results.add(search(query))

        query.emit_source_stats(self.source, results)
        return results


class InternalPositionSource(CellPositionMixin,
                             WifiPositionMixin, PositionSource):
    """A position source based on our own crowd-sourced internal data."""

    fallback_field = None  #:
    source = DataSource.internal  #:

    def should_search(self, query, results):
        if not super(InternalPositionSource, self).should_search(
                query, results):  # pragma: no cover
            return False
        if not (self.should_search_cell(query, results) or
                self.should_search_wifi(query, results)):
            return False
        return True

    def search(self, query):
        results = self.result_type().new_list()

        for should, search in (
                (self.should_search_wifi, self.search_wifi),
                (self.should_search_cell, self.search_cell)):

            if should(query, results):
                results.add(search(query))

        query.emit_source_stats(self.source, results)
        return results

@@ -370,24 +370,28 @@
 %0A%0Aclass 
+Base
 Internal
 RegionSo
@@ -386,94 +386,21 @@
 rnal
-Region
 Source(
-CellRegionMixin,%0A                           WifiRegionMixin, RegionSource
+object
 ):%0A 
@@ -411,15 +411,8 @@
 %22%22A 
-region 
 sour
@@ -598,24 +598,28 @@
 t super(
+Base
 Internal
 RegionSo
@@ -610,22 +610,16 @@
 Internal
-Region
 Source, 
@@ -1305,16 +1305,65 @@
 nSource(
+BaseInternalSource,%0A                             
 CellPosi
@@ -1420,16 +1420,45 @@
 onMixin,
+%0A                            
  Positio
@@ -1546,818 +1546,254 @@
 %22%22%0A%0A
-    fallback_field = None  #:%0A    source = DataSource.internal  #:%0A%0A    def should_search(self, query, results):%0A        if not super(InternalPositionSource, self).should_search(%0A                query, results):  # pragma: no cover%0A            return False%0A        if not (self.should_search_cell(query, results) or%0A                self.should_search_wifi(query, results)):%0A            return False%0A        return True%0A%0A    def search(self, query):%0A        results = self.result_type().new_list()%0A%0A        for should, search in (%0A                (self.should_search_wifi, self.search_wifi),%0A                (self.should_search_cell, self.search_cell)):%0A%0A            if should(query, results):%0A                results.add(search(query))%0A%0A        query.emit_source_stats(self.source, results)%0A        return results
+%0Aclass InternalRegionSource(BaseInternalSource,%0A                           CellRegionMixin,%0A                           WifiRegionMixin,%0A                           RegionSource):%0A    %22%22%22A region source based on our own crowd-sourced internal data.%22%22%22
 %0A

Remove code duplication in internal module.