import { Style } from '../Style';
import { getCssWithThemedTokens } from './theme.utils';
import { Token } from '../Token';
import { ThemeStyles } from '../../styles/defaults/themes.interface';
import { htmlTags } from '../style.interface';

/**
 * Helper function to determine if a property key is a selector
 * @param styleKey
 * @returns
 */
export const isSelector = (property: string): boolean => {
  const selectorPrefixes = [':', '&:', '>', '.', '::', '@'];
  const found = selectorPrefixes.find((prefix) => property.startsWith(prefix));

  return found !== undefined;
};
/**
 * Force first letter uppercase on a word
 * @param string string
 * @returns
 */
export const makeFirstLetterUppercase = (string: string) => {
  if (string.length === 0) {
    return string;
  }
  return string[0].toUpperCase() + string.substring(1);
};

export const createStylesFromObject = (
  objectStyles: any
): Record<string, Style> => {
  const styles: any = {};
  // use default styles
  const keys = Object.keys(objectStyles);
  keys.forEach((key) => {
    const value = objectStyles[key];
    const values = [];
    if (Array.isArray(value)) {
      value.forEach((entry: any) => {
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        //@ts-ignore
        styles[key] = values.push(createStylesFromObject(entry));
      });
    } else {
      styles[key] = new Style({
        id: key,
        value,
        baseComponent: '',
        variant: 'default'
      });
    }
  });
  return styles;
};

export const getStyleValue = () => {};

export const toStylesObject = ({
  value,
  withColorsFromPaletteId,
  lookup
}: {
  value: Record<string, Style>;
  withColorsFromPaletteId?: string; // this is actually the paletteId ('dark' or 'light')
  lookup: { [id: string]: string };
}): object => {
  const obj: any = {};
  Object.keys(value).forEach((key) => {
    const style = value[key];

    if (style.baseComponent) {
      if (!obj[style.baseComponent]) {
        obj[style.baseComponent] = {};
      }
    }
  });

  Object.keys(value).forEach((key) => {
    const style = value[key];

    if (style.baseComponent) {
      obj[style.baseComponent][style.variant] = getCssWithThemedTokens({
        value: style.value,
        lookup,
        withColorsFromPaletteId,
        withRawValue: true
      });
    }
  });
  return obj;
};

export const toApphouseStyles = ({
  value,
  withColorsFromPaletteId,
  lookup
}: {
  value: Record<string, Style>;
  withColorsFromPaletteId?: string;
  lookup: { [id: string]: string };
}): ThemeStyles => {
  const baseStyles: any = toStylesObject({
    value,
    withColorsFromPaletteId,
    lookup
  });

  let styles = JSON.stringify(baseStyles);
  Object.keys(lookup).forEach((key) => {
    styles = styles.replaceAll(`${key}"`, `${lookup[key]}"`);
  });

  return JSON.parse(styles) as ThemeStyles;
};

export const objectifyStylesWithBaseColors = ({
  value
}: {
  value: Record<string, Style>;
  theme?: 'dark' | 'light';
  colors: { [colorId: string]: string };
  tokens: Record<string, Token>;
}): object => {
  const obj: any = {};
  Object.keys(value).forEach((key) => {
    const style = value[key];

    if (style.baseComponent) {
      if (!obj[style.baseComponent]) {
        obj[style.baseComponent] = {};
      }
    }
  });

  Object.keys(value).forEach((key) => {
    const style = value[key];

    if (style.baseComponent) {
      obj[style.baseComponent][style.variant] = {};
    }
  });
  return obj;
};

export const camelcaseifyCssProperty = (property: string): string => {
  const words = property.replaceAll('_', '-').split('-');
  let camelcaseProperty = '';
  words.forEach((word: string, i: number) => {
    if (i === 0) {
      camelcaseProperty = word;
    } else {
      camelcaseProperty = camelcaseProperty + makeFirstLetterUppercase(word);
    }
  });

  return camelcaseProperty;
};

// import { CSSProperties } from "glamor";
// import { CssPropertyStyle, Style } from "./Style";

// export const getPropertyValue = (value: any) => {
//   try {
//     const localStyles: any = {};
//     if (typeof value !== "object") {
//       return value;
//     }

//     Object.keys(value).forEach((key) => {
//       const it = value[key];
//       if (!it && it !== 0) {
//         return;
//       }
//       if (it === 0) {
//         //console.warn("x342", { it, itKey: key });
//         localStyles[key] = 0;
//         return;
//       }
//       const stylePropertyValues = getPropertyValue(value[key]);
//       const hasChildren = Object.keys(stylePropertyValues)?.length > 0;
//       if (!hasChildren) {
//         // accumulate styles
//         localStyles[key] = stylePropertyValues;
//       }
//       if (hasChildren) {
//         localStyles[key] = {};
//         localStyles[key] = getPropertyValue(stylePropertyValues);
//       }
//     });
//     return localStyles;
//   } catch (error) {
//     console.log({ Error: "Error getting property values", error });
//     return {};
//   }
// };

// export const isSelector = (styleKey: string): boolean => {
//   let selector = false;

//   if (styleKey.startsWith(":") || styleKey.startsWith("&:")) {
//     selector = true;
//   }

//   return selector;
// };
// export const getPropertyValuePairs = (
//   cssStyles: CSSProperties
// ): CssPropertyStyle[] => {
//   let propertyStyles: CssPropertyStyle[] = [];
//   Object.keys(cssStyles).forEach((key: string) => {
//     const selector = isSelector(key);
//     const ps: CssPropertyStyle = {
//       isSelector: selector,
//       property: key,
//       value: selector ? cssStyles[key] : cssStyles[key],
//     };
//     propertyStyles = [...propertyStyles, ps];
//   });

//   return propertyStyles;
// };

// export const makeFirstLetterUppercase = (string: string) => {
//   if (string.length === 0) {
//     return string;
//   }
//   return string[0].toUpperCase() + string.substring(1);
// };

// export const depthOf = (object: any) => {
//   let level = 1;
//   for (let key in object) {
//     if (!object.hasOwnProperty(key)) continue;

//     if (typeof object[key] == "object") {
//       const depth = depthOf(object[key]) + 1;
//       level = Math.max(depth, level);
//     }
//   }
//   return level;
// };

// const getHtmlFromId = (id: string) => {
//   if (id.indexOf("button") >= 0) {
//     return "button";
//   }

//   if (id.indexOf("heading") >= 0) {
//     return "h1";
//   }

//   if (id.indexOf("text") >= 0) {
//     return "p";
//   }

//   if (id.indexOf("input") >= 0) {
//     return "input";
//   }

//   if (id.indexOf("label") >= 0) {
//     return "label";
//   }

//   return "div";
// };

// export const getFlattenedStyles = (cssStyles: any): Record<string, Style[]> => {
//   let localStyles: Record<string, Style[]> = {};

//   const getStyles = (
//     current: any,
//     level: number,
//     currentPath?: string
//   ): Style[] => {
//     let localStyle: Style[] = [];
//     const keys = Object.keys(current);

//     keys?.forEach((key) => {
//       const currentStyles = current[key];
//       const variant = level === 0 ? "default" : key;

//       const localDepth = depthOf(localStyle);

//       let id = key;
//       if (currentPath && level !== 0) {
//         id = `${currentPath}${makeFirstLetterUppercase(key)}`;
//       }

//       const childDepth = depthOf(currentStyles);

//       if (childDepth > 1) {
//         const s = getPropertyValuePairs(currentStyles);
//         const hasSelectors = s.find((item) => item.isSelector);

//         if (!hasSelectors) {
//           return mergeStyles(currentStyles, level + 1, key);
//         }
//       }

//       if (localDepth === 1) {
//         const style = new Style(
//           id,
//           getPropertyValuePairs(currentStyles),
//           currentPath || key,
//           variant,
//           undefined,
//           undefined,
//           getHtmlFromId(id)
//         );

//         if (localStyles[id]) {
//           localStyles[id] = [...localStyles[id], style];
//         } else {
//           localStyles[id] = [style];
//         }
//       }
//     });

//     return localStyle;
//   };

//   mergeStyles(cssStyles, 0);
//   return localStyles;
// };

// const cssStyles = toJS(styles);
// export const defaultsStylesRaw = getPropertyValue(cssStyles);

// export const defaultsStyles = getFlattenedStyles(defaultsStylesRaw);

/**
 * Attempt to get a preview tag based on an item from the base component list
 * @param baseComponent string from baseComponent list
 * @returns an html tag (it will default to div if no match is found)
 */
export const getPreviewWithTagFromBaseComponent = (baseComponent: string) => {
  let previewWithTag = htmlTags.includes(baseComponent)
    ? baseComponent
    : undefined;
  if (!previewWithTag) {
    if (baseComponent === 'button') {
      previewWithTag = 'button';
    } else if (baseComponent === 'list') {
      previewWithTag = 'ul';
    } else if (baseComponent === 'link') {
      previewWithTag = 'a';
    } else if (baseComponent === 'typography') {
      previewWithTag = 'p';
    } else if (baseComponent === 'custom') {
      previewWithTag = 'SearchInput';
    } else {
      previewWithTag = 'div';
    }
  }
  return previewWithTag;
};

/**
 * Attempt to get a preview tag based on the property keys on a object
 * @param cssObj object representing the styles
 * @returns an html tag (it will default to div if no match is found)
 */
export const getPreviewWithTagBasedOnObjectProperties = (
  obj: {
    [id: string]: any;
  },
  k?: string
): string => {
  if (k && k.toLocaleLowerCase().includes('button')) {
    return 'button';
  }
  let previewWithTag = 'div';
  Object.keys(obj).forEach((property) => {
    const value = obj[property];
    if (typeof value === 'string') {
      const key = property.toLocaleLowerCase();
      if (
        key.indexOf('font') >= 0 ||
        key.indexOf('typography') >= 0 ||
        key.indexOf('text') >= 0
      ) {
        previewWithTag = 'p';
      }

      if (key.indexOf('input') >= 0) {
        previewWithTag = 'input';
      }

      if (key.indexOf('button') >= 0) {
        previewWithTag = 'button';
      }
    }
    if (typeof value === 'object') {
      // if we have not found a matching at the upper object keys, let's look at the children
      if (previewWithTag === 'div') {
        previewWithTag = getPreviewWithTagBasedOnObjectProperties(value);
      }
    }
  });

  return previewWithTag;
};
